多行数学结果不同于单行

时间:2018-12-28 07:27:45

标签: c++ floating-point

我在一些浮点数学运算上遇到问题,我发现如果我在一行上进行数学运算,则会将-0传递给tan(),并且如果我在两行上进行运算,则会得到0传递给tan()。看看:

float theta = PI / 2.f;
float p = (PI / 2.f) - theta;
float result = tan(p);

上面的p = -0,结果= -4.37 ...

float theta = PI / 2.f;
float p = PI / 2.f;
p -= theta;
float result = tan(p);

上面的p = 0,结果= 0。

谁能解释其中的区别?我认为-0是由tan()导致的结果,尽管我在Google上找不到任何能解释原因的信息。为什么完全相同的计算跨不同的行会导致不同的答案?

谢谢

3 个答案:

答案 0 :(得分:5)

可能是由于PI的类型

如果您使用double,它将更改为float,然后结果 就像您所代表的那样。

但是,如果PI为float,则这两个测试方案都相等。

答案 1 :(得分:4)

@Naor所说的可能是正确的。但我想添加些东西。

您可能不会得到-4.37xx,但会得到-4.37xxxe-xx,这是一个很小的负数。

由于您总是会在浮点数学运算中出错。我说没有必要更改您的代码。两种剪裁都是正确的。

答案 2 :(得分:0)

所以我认为这是正在发生的事情

在两个示例中,PI都是一个定义,可能是这样定义的:

#define 3.14 //and some more digits

在C ++中,这样的数字被视为双精度数字。

预处理后,此表达式:

PI / 2.0f

将被视为双重类型的prvalue。这意味着该行隐藏了另一项操作:

float theta = PI / 2.f;

这是两次浮点转换,在这种情况下肯定会失去一些精度。

在第一个示例中,这也发生在这里:

float p = (PI / 2.f) - theta;

,但仅在评估整个表达式之后。请注意,在此求值过程中,(PI / 2.f)仍将是双精度值,但是theta将是浮点数到双精度转换值,这说明了与0.0的结果略有差异。

在最后一个示例中,您首先将(PI / 2.f)转换为float:

float p = PI / 2.f;

在下一行从中减去浮点型theta。哪一个结果必须为0.0,这可能还是编译器进行了优化; )。