可能重复:
Why does Visual Studio 2008 tell me .9 - .8999999999999995 = 0.00000000000000055511151231257827?
C ++
嘿所以我正在创建一个函数来返回给定数字数据类型中的数字位数,但是我在使用双打时遇到了一些麻烦。
我通过将它乘以100亿,然后将数字1乘以1直到双数结束为0来计算其中有多少位数。但是当输入一个双倍的值时,说.7904我永远不会退出功能因为它一直带走从未结束为0的数字,因为.7904的最终结果为7,903,999,988而不是7,904,000,000。
我该如何解决这个问题?谢谢=)!哦,我的代码上的任何其他反馈都是WELCOME!
这是我的功能代码:
/////////////////////// Numb_Digits() ////////////////////////////////////////////////////
enum{DECIMALS = 10, WHOLE_NUMBS = 20, ALL = 30};
template<typename T>
unsigned long int Numb_Digits(T numb, int scope)
{
unsigned long int length= 0;
switch(scope){
case DECIMALS: numb-= (int)numb; numb*=10000000000; // 10 bil (10 zeros)
for(; numb != 0; length++)
numb-=((int)(numb/pow((double)10, (double)(9-length))))* pow((double)10, (double)(9-length)); break;
case WHOLE_NUMBS: numb= (int)numb; numb*=10000000000;
for(; numb != 0; length++)
numb-=((int)(numb/pow((double)10, (double)(9-length))))* pow((double)10, (double)(9-length)); break;
case ALL: numb = numb; numb*=10000000000;
for(; numb != 0; length++)
numb-=((int)(numb/pow((double)10, (double)(9-length))))* pow((double)10, (double)(9-length)); break;
default: break;}
return length;
};
int main()
{
double test = 345.6457;
cout << Numb_Digits(test, ALL) << endl;
cout << Numb_Digits(test, DECIMALS) << endl;
cout << Numb_Digits(test, WHOLE_NUMBS) << endl;
return 0;
}
答案 0 :(得分:2)
这是因为他们的二进制表示,这里将深入讨论:
http://en.wikipedia.org/wiki/IEEE_754-2008
基本上,当一个数字不能用表示时,会使用近似值。
要比较浮点数是否相等,请检查它们的差异是否小于任意精度。
答案 1 :(得分:2)
关于浮点运算的简单总结:
阅读本文,你会看到光明。
如果你更喜欢数学方面,Goldberg的论文总是很好:
http://cr.yp.to/2005-590/goldberg.pdf
长话短说:实数以固定的,不规则的精度存储,导致不明显的行为。这与语言无关,但更多的是如何处理整个实数的设计选择。
答案 2 :(得分:1)
这是因为C ++(像大多数其他语言一样)无法存储具有infinte精度的浮点数。
浮点数存储如下:
sign * coefficient * 10^exponent
如果你使用的是基数10
问题是coefficient
和exponent
都存储为有限整数。
这是在计算机程序中存储浮点的常见问题,通常会出现一个很小的舍入错误。
解决这个问题最常见的方法是:
关于计算小数的问题 如果你得到一个双输入,就无法解决这个问题。您无法确定用户是否实际发送了1.819999999645634565360而不是1.82。
您必须更改输入或更改功能的工作方式。
有关浮点的更多信息,请访问:http://en.wikipedia.org/wiki/Floating_point
答案 3 :(得分:1)
这是因为IEEE浮点标准的实现方式,具体取决于操作。它是精度的近似值。 从不使用if(float == float)的逻辑,永远!
答案 4 :(得分:1)
浮点数以重要数字×baseexponent(IEEE 754)的形式表示。在您的情况下,浮动1.82 = 1 + 0.5 + 0.25 + 0.0625 + ...
由于只能存储有限的数字,因此如果浮点数不能表示为相关基数中的终止扩展(在该情况下为基数2),则会出现舍入错误。
答案 5 :(得分:0)
您应该始终检查浮点数的相对差异,而不是绝对值。
您也需要阅读this。
答案 6 :(得分:0)
计算机不会准确存储浮点数。要完成您正在进行的操作,您可以将原始输入存储为字符串,并计算字符数。