如果我有两个表示精确整数的随机浮点数或双精度数(在32位整数的范围内),我是否可以期望它们之间的任何和所有加法,减法和乘法运算产生整数浮点数/双精度数而无小数部分?
float x = randInt();
float y = randInt();
float resultAdd = x + y;
float resultSub = x - y;
float resultMul = x * y;
if(fract(resultAdd) == 0.f && fract(resultSub) == 0.f && fract(resultMul) == 0.f){
// will this section always execute, assuming no overflow occurred?
}
每个人都知道永远不要相信浮点精度,但是我想在适当的地方重建信任。鉴于某些解释语言(不明智地)使用浮点数/双精度数作为通用“数字”类型的基础,因此重要的是要知道哪些操作可以将浮点数的状态保留为整数。
答案 0 :(得分:2)
IEEE-754单精度float
仅具有24位尾数,因此显然不能完全表示32位范围内的所有整数
例如,如果x = 16777216.0f,y = 1.0f,则x + y不等于16777217
OTOH IEEE-754双精度具有53位尾数,因此它可以精确地表示每个32位整数。这就是为什么某些语言(例如Javascript或Lua)的所有数值都只有两倍
答案 1 :(得分:0)
重要的是要知道哪些操作可以将浮点数的状态保留为整数。
IEEE-754要求加法,减法,乘法,除法和平方根必须尽可能精确(这是IEEE-754 2008的引用):
每个返回a的计算操作 执行本标准规定的数值结果,就好像它首先产生了中间结果一样 校正至无限精度且范围无限制,然后将中间结果四舍五入,如果 必要,以适合目的地的格式。
因此,如果abs(result)
小于或等于2 24 (对于浮点型)或2 53 (对于双精度型),则会很精确的。
注意:整数浮点值的加,减和乘积将始终导致整数(无论范围如何),但可能不精确(如果结果超出了前面提到的范围)。