【发布时间】:2021-03-05 22:00:31
【问题描述】:
我惊讶地发现浮点到整数的转换是向上舍入而不是截断小数部分。以下是一些使用 Clang 编译的示例代码,可重现该行为:
double a = 1.12; // 1.1200000000000001 * 2^0
double b = 1024LL * 1024 * 1024 * 1024 * 1024; // 1 * 2^50
double c = a * b; // 1.1200000000000001 * 2^50
long long d = c; // 1261007895663739
使用精确数学,浮点值表示
1.1200000000000001 * 2^50 = 1261007895663738.9925899906842624
由于截断,我期望得到的整数是1261007895663738,但实际上它是1261007895663739。为什么?
【问题讨论】:
-
使用精确数学 - 但 C 不使用精确数学。 ideone.com/kG3SD4
-
1.12和1.1200000000000001都不是精确的double值。 -
假设
double映射到 IEEE-754binary64:a=1.1200000000000001e+00 b=1.1258999068426240e+15 c=1.2610078956637390e+15 trunc(c)=1.2610078956637390e+15 floor(c)=1.2610078956637390e+15 ceil(c)=1.2610078956637390e+15 rint(c)=1.2610078956637390e+15 round(c)=1.2610078956637390e+15 d=1261007895663739。换句话说,c是一个整数值,在转换为d的过程中不会丢失任何信息。 -
double a = 1.12; // 1.1200000000000001 * 2^0这是错误的。基数是 10,而不是 2:1.1200000000000001 * 10^0
标签: c floating-point clang ieee-754 floating-point-conversion