繁体   English   中英

为什么将double转换为int可能会得出不同的结果?

[英]Why casting double to int might give different results?

我正在使用固定的小数点数字(使用uint16_t)存储带有2个小数位的百分比。 我发现我将双精度值转换为整数的方式会影响结果值。

const char* testString = "99.85";
double percent = atof(testString);
double hundred = 100;
uint16_t reInt1 = (uint16_t)(hundred * percent);
double stagedDouble = hundred * percent;
uint16_t reInt2 = (uint16_t)stagedDouble;

输出示例:

percent:      99.850000 
stagedDouble: 9985.000000
reInt1:       9984
reInt2:       9985

在0到10000(定点表示)之间的所有值中,大约47%可见该错误。 使用stagedDouble转换时,它根本不会出现。 而且我不明白为什么两个整数不同。 我正在使用GCC 6.3.0。

编辑:改进了代码段,以显示变量percent并统一两个语句之间的系数。 100更改为double似乎是质量更改,可能会影响输出,但不会更改程序中的任何内容。

percent浮动吗? 如果是这样,请查看您要乘的类型。

reInt1double * floatstagedDoubleint * float 混淆浮点数学运算会导致这些类型的舍入错误。

将100都更改为doubleint得到相同的答案。

报告的行为与声明为float percent一致,并且对floatdouble使用IEEE 754基本的32位和64位二进制浮点。

uint16_t reInt1 = (uint16_t)(100.0 * percent);

由于100.0是一个double恒定,此转换percentdouble ,在执行乘法double ,并将结果转换uint16_t 乘法可能具有非常小的舍入误差,最大为双精度格式的½ULP,相对误差约为2 -53

double stagedDouble = 100 * percent;
uint16_t reInt2 = (uint16_t)stagedDouble;

由于100是一个int常量,因此将100转换为float ,在float执行乘法,然后将结果转换为uint16_t 乘法中的舍入误差可能高达float格式的1/2 ULP,相对误差约为2 -24

由于所有值都接近整数的百分之一,因此上/下的错误比率为50:50,结果将接近整数阈值所需结果的一半。 在乘法中,所有值分别为0、25、50或100的百分之一将是精确的(因为25/100是¼,这在二进制浮点数中可精确表示),因此96/100将具有舍入错误。 如果floatdouble舍入误差的方向表现为独立的,统一的随机变量,则大约一半会在不同方向上舍入,从而产生不同的结果,从而导致约48%的不匹配,这与问题中报告的47%一致。

(但是,当我测量实际结果时,我发现floatdouble方法之间有42%的差异。我怀疑这与舍入前float乘法中的尾随位有关—分布可能不像两种可能性。可能是OP的代码以某种方式准备percent值,而不是将整数值除以100。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM