为什么 std::round(sin(pi/6)) 不等于 1?

Why does std::round(sin(pi/6)) not equal 1?

本文关键字:不等于 pi std round sin 为什么      更新时间:2023-10-16

cpp首选项文档指出,std::round将在"中间情况下"专门从零四舍五入。虽然文字0.5是这样,但std::sin(pi/6)却不是这样。我认为这可能是浮点错误,所以我打印了值,但它正好0.5.但是,在检查二进制表示后,我可以看到它们确实以不同的方式表示。我在下面提供了用于进行这些检查的代码。

#include <iostream>
#include <stdio.h>
#include <cmath>
int main(int argc, char * argv[])
{
double const pi = std::acos(-1);
double const a = std::sin(pi/6);
double const b = 0.5;
std::cout << "round(" << a << ") = " << std::round(a) << "n";
auto pa = reinterpret_cast<const unsigned char *>(&a);
auto pb = reinterpret_cast<const unsigned char *>(&b);
std::cout << "a = 0x";
for (size_t i = 0; i != sizeof(double); ++i) {
printf("%02x", pa[i]);
}
std::cout << "nb = 0x";
for (size_t i = 0; i != sizeof(double); ++i) {
printf("%02x", pb[i]);
}
std::cout << "n";
}
round(0.5) = 0
round(0.5) = 1
a = 0xffffffffffffdf3f
b = 0x000000000000e03f

所以我的问题是这种舍入行为是 c++ 规范的一部分还是这是一个错误?无论如何,是否有一些通用方法可以"纠正"sin返回的值的表示形式?我不确定它是什么格式,因为根据我对 IEEE-754 的了解,它看起来应该是 NaN。虽然据我了解,c++ 不能保证 IEEE-754 浮点表示?

问题是您没有打印具有足够有效数字的值。 当我用std::setprecision(20)提高精度时,我得到:round(0.49999999999999994449) = 0

您可以通过更改代码或在此在线计算器的底部十六进制字段中输入3fdfffffffffffff来亲自查看以下内容:https://baseconvert.com/ieee-754-floating-point

表示形式看起来像 NaN,因为您正在向后读取它。 x86/x64 具有小端浮点数。所以你应该读到它从高到低地址,产生0x3fdfffff...,这当然略小于0.5。