双打和算术

时间:2012-03-10 20:13:27

标签: c++ visual-c++ math numbers date-arithmetic

我使用MSVC2008编译并运行此代码

long double x = 111111111;
long double y = 222222222;
long double Z = x * y;

cout << z << endl;

调试时,z等于

24691357975308640

数学z应为

24691357975308642

发生了什么事?

4 个答案:

答案 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