Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
地板的奇怪行为() 我开发了一个C++应用程序(Windows 7, 64位,VS 2008),其中使用以下公式(所有VAR都是双类型):_C++_Math_Double - Fatal编程技术网

地板的奇怪行为() 我开发了一个C++应用程序(Windows 7, 64位,VS 2008),其中使用以下公式(所有VAR都是双类型):

地板的奇怪行为() 我开发了一个C++应用程序(Windows 7, 64位,VS 2008),其中使用以下公式(所有VAR都是双类型):,c++,math,double,C++,Math,Double,其思想是将一个数字缩短为给定的小数位数。我认为有更好的方法可以做到这一点,但这不是这里的问题(但如果你有更好的选择,请付诸行动!) mValue来自用户输入,因此在大多数情况下,小数位数已经可以了。但在某些情况下,输出与输入不同 例如,mStepping的值为0.1(应该四舍五入到小数点后一位)。现在,如果mValue的值为14.6,则一切正常。如果mValue为14.7,则结果为14.6 那么,为什么地板(14.7/0.1)*0.1=14.6? 我测试了其他值,其中大约20%的值相差0.1。我

其思想是将一个数字缩短为给定的小数位数。我认为有更好的方法可以做到这一点,但这不是这里的问题(但如果你有更好的选择,请付诸行动!)

mValue来自用户输入,因此在大多数情况下,小数位数已经可以了。但在某些情况下,输出与输入不同

例如,mStepping的值为0.1(应该四舍五入到小数点后一位)。现在,如果mValue的值为14.6,则一切正常。如果mValue为14.7,则结果为14.6

那么,为什么地板(14.7/0.1)*0.1=14.6?

我测试了其他值,其中大约20%的值相差0.1。我进一步挖掘,发现14.7/0.1的二进制编码与147.0不同:

14.7/0.1 = ff ff ff ff ff 5f 62 40
147.0    = 00 00 00 00 00 60 62 40

我知道同一个数字可以用不同的方式编码为双精度。但是为什么floor()处理它们的方式不同呢?我该怎么对付它呢

通常的问题是:并非所有精确的十进制分数都可以用二进制表示。在您的情况下,它也是
0.1
14.7
。除以0.1,实际上不是147,而是低于它的一小部分:

14.699999999992928945726423989981412887573732421875

乘以0.1:

0.100000000000000551151231257827021181583404541

您将到达:

146.999999999797971578290569595992565155029296875

我想你现在开始看到问题了,对吧?这个数字显然会给你146

你能做些什么来对付它?如果需要精确的小数结果,请使用表示小数点的数字类型或bignum库

哦,还有一个旁注:不,相同的数字没有不同的
double
表示法。只是你对数字的理解和它的行为与浮点数学不同

我知道同一个数字可以用不同的方式编码为 加倍

你不明白的是14.7/0.1和147.0不是同一个数字

例如,编写以下测试代码:

if (14.7/0.1 == 147.0)
{
    cout << "We are equal!";      
}
else
{
    cout << "We are different!";
}
if(14.7/0.1==147.0)
{

cout问题在于,您使用的任何数字都不能以二进制浮点格式精确表示。这就是二进制浮点的本质。有关更多详细信息,请阅读

您的两个号码对应的号码是:

  • 0.1=+0.10000 00014 90116 11938 47656 25
  • 14.7=+14.69999 98092 65136 71875
因此,
14.7/0.1
首先被计算,因为这些值不是完全可表示的,所以正好计算出一个小于
147
的值。所以当你
floor
它时,你把它变成146。因此你观察到的结果

我知道同一个数字可以用不同的方式编码为双精度

通常情况并非如此。您的问题是14.7和0.1都不能精确表示。问题与表示的唯一性无关


<> P> >,为了精确地执行你的算术运算,你需要使用十进制算术。这不是内置到C++中的东西,你需要使用第三方库。除了关于十进制和小数浮点表示的不精确性的其他答案,Fror()在将十进制表示法计算为浮点数的有效位数时,也是错误的选择。应改为-并且结果不应存储在浮点数中,而应以其他方式存储。

舍入错误。在浮点数表示法中,14.7近似为14.69999999999…使用
第(轮)
取而代之。@H2CO3这是一个不错的小收入者。谢谢大家。我仍然在为自己如此愚蠢而头痛。自我提醒:千万不要在假期前的最后一天发布到stackoverflow…我不太确定我是否同意。因为14.7不能表示,所以任何舍入量都没有帮助。你通常做的是应用小数位数限制当您将格式设置为文本时。但保留基础值不变。或使用十进制算术。@DavidHeffernan-您有一个点。只有在使用某种十进制(定点、有理数)表示法时,舍入才有用。
if (14.7/0.1 == 147.0)
{
    cout << "We are equal!";      
}
else
{
    cout << "We are different!";
}