Unit64使用mingw与float相乘

时间:2012-12-03 00:55:41

标签: mingw calculator

我在使用float函数执行unit64变量的乘法时观察到mingw的奇怪行为。这是编译器中的问题吗?

以下是我的代码:

#include <iostream>
using namespace std;

int main() {

    uint64_t myvar = 4293057;
    float mycrasher = 1000;
    myvar = myvar*mycrasher;
    cout << "value after mul is "<<myvar << endl; 
    return 0;
}

显示的输出值是4293057024而不是4293057000 !!

1 个答案:

答案 0 :(得分:1)

IEEE754单精度值(例如float)只有大约七位小数的精度。除此之外,它是不精确的。您甚至不必将它乘以1000,将其乘以10会得到42930568

您可以通过以下代码查看正在发生的事情:

#include <iostream>
int main () {
    float xyzzy = 42930570;
    std::cout.precision (5);
    std::cout << "xyzzy is " << std::fixed <<xyzzy << '\n';
    return 0;
}
输出不那么精确的

42930568.00000

为了更全面地解释,IEEE754浮点值的精度有限,因为它们具有可用于此目的的有限位数。单精度值的长度为32位,并且对于分数具有23位(其他位用于符号和指数)。这23位等于大约七位小数。您可以找到进一步的分析here

数字42930570无法在单个精度值中精确表示。您要么得到0x4c23c462的位42930568,要求得0x4c23c463的下一个42930572


他们被转换为float而不是uint64_t的原因是因为这就是标准所说的。在C ++ 03中,“乘法运算符”部分(5.6)表示:

  

通常的算术转换是在操作数上执行的,并确定结果的类型。

通常的算术转换详见第5节第9段,包括:

  • 如果任一操作数的类型为long double,则另一个操作数应转换为long double。
  • 否则,如果任一操作数为double,则另一个操作数应转换为double。
  • 否则,如果任一操作数为float,则另一操作数应转换为float。
  • 处理整数类型的更多东西(它实际上不是 说的,我在解读)。

由于您有floatuint64_t,因此上面的第三个要点涵盖了这一点。在“浮动 - 积分转换”部分(4.9)中,我们看到:

  

整数类型或枚举类型的右值可以转换为浮点类型的右值。如果可能,结果是准确的。否则,它是实现定义的下一个较低或较高可表示值的选择。

因此 为什么你会看到失去精确度。

在C ++ 11中没有改变。措辞有所改变,而且更加冗长,但这些部分仍然归结为相同的结果。