【问题标题】:Why does int/float multiplication lead to different results?为什么 int/float 乘法会导致不同的结果?
【发布时间】:2013-12-23 13:38:51
【问题描述】:

如果我像下面这样将浮点数和整数相乘,为什么所有乘法都会导致不同的结果?我的期望是一致的结果。我认为在这两种情况下,int 值都会在乘法之前隐式转换为浮点数。但似乎有区别。这种处理方式不同的原因是什么?

int multiply(float val, int multiplier)
{
    return val * multiplier;
}

int multiply2(float val, int multiplier)
{
    return float(val * multiplier);
}

float val = 1.3f;

int result0 = val * int(10); // 12
int result1 = 1.3f * int(10); // 13
int result3 = multiply(1.3f, 10); //12 
int result4 = multiply2(1.3f, 10); // 13

谢谢 托尔斯滕

【问题讨论】:

  • 这是真正的代码吗?我得到了相同的结果,但我不明白为什么会不同。
  • 第二个表达式可以在编译时求值——你用的是什么编译器?查看它产生的字节码。
  • 在 Ubuntu 上使用 g++ 4.7.3 进行了尝试:两个乘法都导致 13
  • 编译器是 Visual Studio 2010 的内置版本。是的,它是真正的代码 =)
  • @Floris:你是对的。反汇编显示对于 result1 没有执行乘法运算。仅采用编译时 const 值。

标签: c++ floating-point multiplication


【解决方案1】:

你可能发生的事情是:

假设 IEEE 或类似的浮点数,1.3 无法表示,很可能是 1.299999 乘以 10 是 12.99999,然后截断为 int 是 12。

但是 1.3 * 10 可以在编译时进行评估,从而最有可能得到 13 的准确表示。

根据您的代码的实际结构、使用的编译器以及与它一起使用的设置,它可以评估 1 到 12 或 13,具体取决于它是在运行时执行此操作,还是在编译时执行此操作。

为了完整起见,我可以使用以下代码重现它:

extern int result0;
extern int result1;

float val = 1.3f;

void foo( )
{   
 result0 = val * int(10); // 12
 result1 = 1.3f * int(10); // 13
}

【讨论】:

  • 是否允许编译器使用不同的表示进行编译时计算?
  • @sftrabbit 我的猜测是实现定义
  • @sftrabbit:我手头没有标准报价,但它是。这也是模板不允许非类型浮点参数的原因。
  • @sftrabbit 它甚至允许动态使用不同的表示。 §5/11:“浮动操作数的值和浮动表达式的结果可以用比类型要求的更高的精度和范围来表示;类型不会因此而改变”。它不是实现定义的,而是未指定的。 (E.i. 实现不需要记录它做了什么,甚至连续两次做同样的事情。)事实上,它可以很容易地根据优化级别而改变。
  • @JamesKanze 我认为这受到…::is_iec559FLT_EVAL_METHOD 的限制。将前者定义为 true 并将后者定义为 0 的编译器不应执行任何此类操作。将FLT_EVAL_METHOD 定义为12 的编译器应生成根据各自模型进行计算的程序。
猜你喜欢
  • 2011-10-07
  • 2017-02-21
  • 1970-01-01
  • 1970-01-01
  • 2012-09-27
  • 2015-02-06
  • 2013-06-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多