我使用MSVC2008编译并运行此代码
long double x = 111111111;
long double y = 222222222;
long double Z = x * y;
cout << z << endl;
调试时,z
等于
24691357975308640
数学z
应为
24691357975308642
发生了什么事?
答案 0 :(得分:7)
双打仅精确到16 digits左右。如果我计算正确,那么你有17位数,并且最多16位。如果你想做这种数学,并且只有整数,那么使用整数。对于数字较大的数字,您需要使用uint64_t
。
答案 1 :(得分:4)
什么都没发生。双精度具有有限的精度,对于该精度,您获得的值是正确的。您选择打印有关精度信息(即有效数字)丢失的值的方式是一个令人遗憾的缺点。
例如,对于1 + 11 +(1)+52 float(see here),我们有53位的精度,给出53×log 10 2的十进制数字精度,即15.所以我们只打印15位数字:
#include <iomanip>
#include <iostream>
std::cout << std::setfill('0') << std::setprecision(15) << std::scientific
<< Z << std::endl;
结果是:
2.469135797530864e+16
现在我们制作了精确清单,结果确实是正确的。
如果你不喜欢代码中的魔术15
,你应该#include <limits>
并使用:
std::numeric_limits<decltype(Z)>::digits10
答案 2 :(得分:1)
浮点运算正在进行中。 This是一本很好的读物。基本上,计算机存储和处理浮点数时会遇到问题,因此会出现这类算术错误。
答案 3 :(得分:1)
通常,人们可以写一本书来回答你的问题。长话短说 - 浮点运算正在进行中。见Floating Point。此外,将双值转换为ASCII(用于显示)也很难并且不准确。您可能还想查看arbitrary precision arithmetics。