请考虑以下代码:
0.1 + 0.2 == 0.3 -> false
Run Code Online (Sandbox Code Playgroud)
0.1 + 0.2 -> 0.30000000000000004
Run Code Online (Sandbox Code Playgroud)
为什么会出现这些不准确之处?
关于浮点表示,已经向SO发布了几个问题.例如,十进制数0.1没有精确的二进制表示,因此使用==运算符将其与另一个浮点数进行比较是危险的.我理解浮点表示的原理.
我不明白的是,从数学的角度来看,为什么小数点右边的数字比左边的数字更"特殊"?
例如,数字61.0具有精确的二进制表示,因为任何数字的整数部分始终是精确的.但数字6.10并不准确.我所做的只是将十进制移动到一个地方,然后我突然从Exactopia转到了Inexactville.在数学上,两个数字之间应该没有内在差异 - 它们只是数字.
相比之下,如果我将小数位移到另一个方向以产生数字610,我仍然在Exactopia中.我可以继续向那个方向前进(6100,610000000,610000000000000),它们仍然是精确,准确,准确的.但是一旦小数越过某个阈值,数字就不再精确了.
这是怎么回事?
编辑:为了澄清,我想远离关于行业标准表示的讨论,例如IEEE,并坚持我认为是数学上"纯粹"的方式.在基数10中,位置值为:
... 1000 100 10 1 1/10 1/100 ...
Run Code Online (Sandbox Code Playgroud)
在二进制文件中,它们将是:
... 8 4 2 1 1/2 1/4 1/8 ...
Run Code Online (Sandbox Code Playgroud)
对这些数字也没有任何限制.位置无限增加到左侧和右侧.
我在基于UNIX的系统上遇到问题sprintf没有正确地舍入值.
例如
double tmp = 88888888888885.875
char out[512];
Run Code Online (Sandbox Code Playgroud)
这是88,888,888,888,885.875只是为了让眼睛更容易.我给出了这样一个特别而又大的例子,因为它似乎在较小的数字上工作正常.
我试图以下面的方式使用它
sprintf(out, "%021.2f", tmp);
printf("out = %s\n", tmp);
Run Code Online (Sandbox Code Playgroud)
在Windows上,这会导致:
out = 000088888888888885.88
Run Code Online (Sandbox Code Playgroud)
例如AIX,但在Linux中也显示:
out = 000088888888888885.87
Run Code Online (Sandbox Code Playgroud)
为什么会这样?任何想法以及如何使它在Win/Unix上的行为方式相同
谢谢
可能重复:
在.NET中双重乘法断开?
JavaScript代码:
var n = 1;
while ( n > 0 )
{
n -= 0.1;
document.body.innerHTML += n + "<br/>";
}
Run Code Online (Sandbox Code Playgroud)
我期望:
0.9
0.8
0.7
0.6
0.5
0.4
0.3
0.2
0.1
0
Run Code Online (Sandbox Code Playgroud)
但得到了这个:
0.9
0.8
0.7000000000000001
0.6000000000000001
0.5000000000000001
0.40000000000000013
0.30000000000000016
0.20000000000000015
0.10000000000000014
1.3877787807814457e-16
-0.09999999999999987
Run Code Online (Sandbox Code Playgroud)
谁能解释那里发生了什么?
当乘以一组int并将结果转换为long时,我得到一个不同的答案,而不是当我乘以一组双精度并将结果转换为long时.例如:
int a = 5;
int b = 5;
int c = 7;
int d = 6;
int ee = 6;
int f = 8;
int g = 9;
int h = 6;
int i = 6;
int j = 4;
int k = 8;
int l = 9;
int m = 5;
long x = a * b * c * d * ee * f * g * h * i * j * k * l * …Run Code Online (Sandbox Code Playgroud) 我有基本类型转换的问题.
#include<stdio.h>
int main()
{
printf("%.22f",0.30);
return 1;
}
Run Code Online (Sandbox Code Playgroud)
我得到的输出是0.2999999999999999888978
为什么0.3转换为较小的值
任何帮助非常感谢
Nandish
我的单元测试因此而失败,所以我想知道我是否使用了正确的数据类型?
阅读双重的规格,我认为应该没问题,但这就是发生的事情:
我正在从一个带有值的文件中读取一个字符串0,0175(逗号为十进制sep.)
然后我将它转换为double然后乘以10000.
执行乘法的函数是:
private static double? MultiplyBy10000(double? input)
{
if (!input.HasValue)
{
return null;
}
return input.Value*10000;
}
Run Code Online (Sandbox Code Playgroud)
接下来是来自眼前的窗口:
input.Value
0.0175
input.Value*10000
175.00000000000003
Run Code Online (Sandbox Code Playgroud)
这就是我的单元测试失败的原因,因为我期望175.
双重不够准确吗?
检查其他值:
input.Value*1
0.0175
input.Value*10
0.17500000000000002
input.Value*100
1.7500000000000002
input.Value*1000
17.5
input.Value*10000
175.00000000000003
Run Code Online (Sandbox Code Playgroud)
奇怪的是,我有12个测试用例0,0155 0,0225 0,016 0,0175 0,0095 0,016 0,016 0,0225 0,0235 0,0265
并断言其中4个,其他3个没有这种行为
在执行过程中,
我只是打开了即时窗口,我输入了这样的,
?1.66 + 0.83
Run Code Online (Sandbox Code Playgroud)
因此,此表达式显示以下内容,
2.4899999999999998
Run Code Online (Sandbox Code Playgroud)
实际上该表达式应该已经返回2.49但是返回相同的值并使用不同的浮点数.这有什么问题.?有没有可用于解决此问题的工作.?顺便说一句,我不想格式化上述值.
double c, d, e;
double a = (c - d) / e;
double b = Math.Floor(a);
Debug.WriteLine(a.ToString() + " " + b.ToString());
Run Code Online (Sandbox Code Playgroud)
上面的代码在一个配置中输出"3 2",其中所有数字都是双倍的.这怎么可能?是因为双重操作导致的分数误差?但是我认为a.ToString()应该用整数来表示整数.