我想知道是否有办法克服精确度问题,这似乎是我的机器内部表示浮点数的结果:
为清楚起见,问题归纳为:
// str is "4.600"; atof( str ) is 4.5999999999999996
double mw = atof( str )
// The variables used in the columns calculation below are:
//
// mw = 4.5999999999999996
// p = 0.2
// g = 0.2
// h = 1 (integer)
int columns = (int) ( ( mw - ( h * 11 * p ) ) / ( ( h * 11 * p ) + g ) ) + 1;
Run Code Online (Sandbox Code Playgroud)
在转换为整数类型之前,列计算的结果是1.9999999999999996; 距离2.0的理想结果还差不多.
任何建议最受欢迎.
这是我的VBE(MS Excel 2007 VBA)中的一个小宝石:
?clng(150*0.85)
127
x = 150*0.85
?clng(x)
128
Run Code Online (Sandbox Code Playgroud)
任何人都可以解释这种行为吗?恕我直言,第一个表达式应该产生128(.5舍入到最接近的偶数),或者至少应该两个结果相等.
我以前主要使用整数,在需要截断浮点数或双精度到整数的情况下,我会使用以下内容:
(int) someValue
Run Code Online (Sandbox Code Playgroud)
除非我发现以下情况:
NSLog(@"%i", (int) ((1.2 - 1) * 10)); // prints 1
NSLog(@"%i", (int) ((1.2f - 1) * 10)); // prints 2
Run Code Online (Sandbox Code Playgroud)
(在解释时,请参阅在C#中将float转换为int时的奇怪行为).
简短的问题是:我们应该如何正确地截断浮点数或双精度?(在这种情况下需要截断,而不是"舍入").或者,我们可以说由于一个数字是1.9999999999999而另一个数字是2.00000000000001(粗略地说),截断实际上是正确完成的.所以问题是,我们应该如何转换浮点数或双精度数,以便结果是一个"截断"的数字,这使得常见的用法有意义?
(意图是不使用round,因为在这种情况下1.8,我们确实想要结果1,而不是2)
更长的问题:
我用了
int truncateToInteger(double a) {
return (int) (a + 0.000000000001);
}
-(void) someTest {
NSLog(@"%i", truncateToInteger((1.2 - 1) * 10));
NSLog(@"%i", truncateToInteger((1.2f - 1) * 10));
}
Run Code Online (Sandbox Code Playgroud)
并打印出来2,但它似乎太多的黑客,我们应该用什么小数字来"消除不准确"?是否有更标准或研究的方式,而不是这样的任意黑客?
(注意我们想要截断,而不是在一些用法中舍入,例如,如果秒数为90或118,当我们显示已经过了多少分钟和多少秒时,分钟应显示为1,但不应该四舍五入到2)
我有以下Python代码和输出:
>>> import numpy as np
>>> s = [12.40265325, -1.3362417499999921, 6.8768662500000062, 25.673127166666703, 19.733372250000002, 21.649556250000003, 7.1676752500000021, -0.85349583333329804, 23.130314250000012, 20.074925250000007, -0.29701574999999281, 17.078694250000012, 3.3652611666666985, 19.491246250000003, -0.76856974999999039, -1.8838917499999965, -6.8547018333333085, 4.5195052500000088, 5.9882702500000136, -9.5889237499999922, 13.98170916666669, -2.3662137499999929, 12.111165250000013, -6.8334957499999902, -21.379336749999993, 8.4651301666666967, 2.5094612500000082, -0.21386274999998989, 5.1226162500000072, 14.283680166666699, -4.3340977499999909, -2.7831607499999933, 8.2339832500000085, -12.841856749999991, -6.4984398333333075, -6.2773697499999912, -13.638411749999996, -15.90088974999999, -8.2505068333333043, -19.616496749999996, -4.4346607499999919, -10.056376749999991, -13.581729833333299, -8.2284047499999957, -4.5957137499999945, -5.3758427499999968, -12.254779833333302, 11.207287250000007, -12.848971749999997, -14.449801749999992, -17.247984749999993, -17.475253833333305]
>>> np.mean(s)
1.3664283380001927e-14
>>> np.std(s)
12.137473069268983
>>> (s - np.mean(s)) / np.std(s)
array([ 1.02184806, -0.11009225, 0.56658138, 2.1151954 , ... …Run Code Online (Sandbox Code Playgroud) 例如,0,0.5,0.15625,1,2,3 ......是从IEEE 754转换而来的值.它们的硬编码版本是否精确?
例如:
是
float a=0;
if(a==0){
return true;
}
Run Code Online (Sandbox Code Playgroud)
总是回归真实?其他例子:
float a=0.5;
float b=0.25;
float c=0.125;
Run Code Online (Sandbox Code Playgroud)
a*b总是等于0.125而a*b == c总是如此?还有一个例子:
int a=123;
float b=0.5;
Run Code Online (Sandbox Code Playgroud)
a*b总是61.5?或者一般来说,整数乘以IEEE 754二进制浮点精确?
或者更一般的问题:如果值是硬编码并且值和结果都可以用IEEE 754中的二进制格式表示(例如:0.5 - 0.125),那么值是否精确?
有人刚刚问为什么sum(myfloats)不同sum(reversed(myfloats))。很快就被骗到浮点数学坏了吗?并删除。
但这让我很好奇:仅仅通过以不同的顺序求和,我们可以从很少的浮点数中得到多少个不同的总和?使用三个浮点数,我们可以得到三个不同的总和:
>>> from itertools import permutations
>>> for perm in permutations([0.2, 0.3, 0.4]):
print(perm, sum(perm))
(0.2, 0.3, 0.4) 0.9
(0.2, 0.4, 0.3) 0.9000000000000001
(0.3, 0.2, 0.4) 0.9
(0.3, 0.4, 0.2) 0.8999999999999999
(0.4, 0.2, 0.3) 0.9000000000000001
(0.4, 0.3, 0.2) 0.8999999999999999
Run Code Online (Sandbox Code Playgroud)
我相信加法对于浮点数来说是可交换的(即a + b == b + a)。我们对第一对相加有三个选择,然后对第二个相加有一个“选择”,所以三个和是我们仅用三个值就能得到的最多结果。
我们可以得到三个以上具有四个值的不同总和吗?经过一些实验,我没有发现这样的情况。如果我们不能:为什么不呢?如果可以的话:有多少?五有多少?
正如埃里克刚刚指出的,对于三个以上的值,除了从左到右求和之外,还有不同的可能性,例如(a+b) + (c+d)。我对任何添加数字的方式感兴趣。
注意我说的是 64 位浮点数(我是 Python 爱好者,我知道在其他语言中它们通常被称为双精度浮点数)。
为什么这个C程序输出"错误"?
#include<stdio.h>
void main()
{
float f = 12345.054321;
printf("%f", f);
getch();
}
Run Code Online (Sandbox Code Playgroud)
输出:
12345.054688
Run Code Online (Sandbox Code Playgroud)
但输出应该是,12345.054321.
我在VS2008中使用VC++.
参考BigDecimal课程文件,
n,m = a.precs
prec返回有效位数(n)和最大有效位数(m)a.
我对以下与之相关的输出感到困惑BigDecimal.
require 'bigdecimal'
BigDecimal.new('1').precs # => [9, 18]
BigDecimal.new(1).precs # => [9, 27]
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚为什么当a String传递时,与传递a 相比,最大有效位数会减少Fixnum.
它还会导致任何精度问题吗?
这里的代码是直截了当的,但我不明白结果:
float percent = 0.69f;
int firstInt = (int)(percent*100f);
float tempFloat = percent*100f;
int secondInt = (int)tempFloat;
Debug.Log(firstInt + " " + secondInt);
Run Code Online (Sandbox Code Playgroud)
为什么是firstInt68但是secondInt69?
如果以前曾经问过我,我很抱歉,但我找不到.
我想知道是否有办法计算用作计数器的单精度浮点数达到'最大值'的点(由于丢失而无法再添加其他值的点)精确).
例如,如果我不断添加0.1f到a,float我最终会达到值不会改变的点:
const float INCREMENT = 0.1f;
float value = INCREMENT;
float prevVal = 0.0f;
do {
prevVal = value;
value += INCREMENT;
} while (value != prevVal);
cout << value << endl;
Run Code Online (Sandbox Code Playgroud)
在海湾合作委员会这输出 2.09715e+06
有没有办法用数学方法计算不同的值INCREMENT?我认为理论上它应该是当指数部分float要求移位超过23位时,导致丢失尾数并简单地加0.