比较int和double时出错

时间:2016-05-25 07:29:15

标签: c++

我正在尝试创建一个计算位数的简单函数。我有一些写得很完美的功能但是我坚持这个:

// The number I want to count the digits after the decimal
long double d=33.56;
// Going to modify d but I wan't to keep the original value
long double dTemp=d;
// v to store the part after the decimal and e the part before
long double v, e;

v=modfl(dTemp,&e);

// j is the number of digit after the decimal
int j=0;
while(dTemp!=e)
{
    j++;
    dTemp*=10;
    v=modfl(dTemp,&e);
    std::cout<<"D = "<<dTemp<<" e = "<<e<<" v = "<<v<<std::endl;
}
std::cout<<"J = "<<j<<std::endl;

输出结果为:

D = 335.6 e = 335 v = 0.6
D = 3356 e = 3356 v = 2.27374e-13
D = 33560 e = 33560 v = 2.27374e-12
D = 335600 e = 335600 v = 2.27374e-11
D = 3.356e+06 e = 3.356e+06 v = 2.27374e-10
D = 3.356e+07 e = 3.356e+07 v = 2.27374e-09
D = 3.356e+08 e = 3.356e+08 v = 2.27301e-08
D = 3.356e+09 e = 3.356e+09 v = 2.27243e-07
D = 3.356e+10 e = 3.356e+10 v = 2.27243e-06
D = 3.356e+11 e = 3.356e+11 v = 2.27094e-05
D = 3.356e+12 e = 3.356e+12 v = 0.000226974
D = 3.356e+13 e = 3.356e+13 v = 0.00226974
D = 3.356e+14 e = 3.356e+14 v = 0.0227051
D = 3.356e+15 e = 3.356e+15 v = 0.227051
D = 3.356e+16 e = 3.356e+16 v = 0.269531
D = 3.356e+17 e = 3.356e+17 v = 0.6875
D = 3.356e+18 e = 3.356e+18 v = 0
J = 17

但是,如果你看一下输出的第2行,你有:

  

D = 3356 e = 3356 v = 2.27374e-1

因此,dTemp等于e,while循环仍然继续。

我尝试了什么:

  • 虽然我可能因为无法存储所需数量那么大的数字。这就是我使用长双

    的原因
    • 我尝试了不同类型的变量,但我总是得到相同的结果。

1 个答案:

答案 0 :(得分:3)

直接检查浮点/双/长双数的方程式/非方程式不是一个好习惯。所以我建议使用这样的东西

不相等:

while (abs(dTemp - e) > 1e-12) { ... }

等于:

while (abs(dTemp - e) < 1e-12) { ... }

&#34;微小&#34; number取决于非整数的类型(浮点数或固定精度实数)。 M-Gregoire关于使用std::numeric_limits<double>::epsilon()的评论可能听起来不错,但人们可能会再次遇到问题。由于33.56无法计算为2的正和/或负幂的有限和,因此无法存储!总是存在着巨大的差异。在内部,它的存储方式如下:33.56000000000000227373675443232059478759766(我打印在,但在中,您会得到类似的结果)。所以你可以设置这个&#34; tiny&#34;差异值为&#34;适当&#34; value,足以禁用此内部浮动格式问题。

您可以使用其他方法。 std::ostringstream可以与操纵器setprecision一起使用,将精度设置为&#34;适当的&#34;将数字转换为字符串然后计算字符串中的数字的数字。但它也不是那么简单。

我查看了价值&#33; 33.56&#39;在也是如此。请参阅示例代码:

#include <iostream>
#include <iomanip>

int main() {
  float df = 33.56;
  double dd = 33.56;
  long double dld = 33.56;
  std::cout << std::setprecision(50) << df << std::endl;
  std::cout << std::setprecision(50) << dd << std::endl;
  std::cout << std::setprecision(50) << dld << std::endl;
}

输出结果为:

33.560001373291015625
33.56000000000000227373675443232059478759766
33.56000000000000227373675443232059478759766

因此,如果浮点数1e-5可用于间隙值,则双1e-14在这种情况下似乎是正确的值。