我正在尝试创建一个计算位数的简单函数。我有一些写得很完美的功能但是我坚持这个:
// 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循环仍然继续。
我尝试了什么:
虽然我可能因为无法存储所需数量那么大的数字。这就是我使用长双
的原因答案 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
(我打印在perl,但在c++中,您会得到类似的结果)。所以你可以设置这个&#34; tiny&#34;差异值为&#34;适当&#34; value,足以禁用此内部浮动格式问题。
您可以使用其他方法。 std::ostringstream
可以与操纵器setprecision
一起使用,将精度设置为&#34;适当的&#34;将数字转换为字符串然后计算字符串中的数字的数字。但它也不是那么简单。
我查看了价值&#33; 33.56&#39;在c++也是如此。请参阅示例代码:
#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在这种情况下似乎是正确的值。