浮点数运算中z*y与z/x是否恒等?(y=1/x且x,y可精确表示)
浮点数运算中
z*y与z/x(当y=1/x且x、y均精确可表示)是否恒等? 核心结论
num/2与num*0.5完全可互换
在Float.MIN_VALUE至Float.MAX_VALUE范围内,num/2和num*0.5的运算结果完全一致。因为0.5是2的负一次方,属于二进制浮点数可以精确表示的数值,除法和乘法操作在这种场景下不会引入任何额外舍入误差,结果完全等价。通用场景下
z*y恒等于z/x
当满足以下全部条件时,z*y与z/x的结果必然相等:
- y = 1/x
- x和y都能被二进制浮点数精确表示(即两者的二进制展开均为有限位,比如x=4、y=0.25;x=8、y=0.125这类数值)
z*y和z/x均落在Float.MIN_VALUE至Float.MAX_VALUE范围内(避免溢出或下溢导致的精度丢失)
原因分析
二进制浮点数的存储机制决定了,只有当一个数的二进制表示是有限位时,才能被精确存储。当x和y互为精确倒数且都能精确表示时,y在浮点数中就是1/x的精确值,此时z乘以y等价于z除以x——浮点数的乘法和除法在处理这种精确逆运算时,不会产生额外的舍入误差,只要运算结果不超出范围,两种操作的结果完全一致。
验证代码
单个案例测试
document.write(123.456*4 == 123.456/0.25); document.write("<br/>"); document.write(24.68/16 == 24.68*0.0625); document.write("<br/>"); document.write(98.765/2 == 98.765*0.5);
循环批量验证
// 验证num*0.5与num/2 for(let i=0;i<10000;i++){ const r=Math.random()*10000; if(r*0.5!=r/2){ document.write(r+"<br/>"); break; } } // 验证num*4与num/0.25 for(let i=0;i<10000;i++){ const r=Math.random()*10000; if(r*4!=r/0.25){ document.write(r+"<br/>"); break; } } // 验证num*0.125与num/8 for(let i=0;i<10000;i++){ const r=Math.random()*10000; if(r*0.125!=r/8){ document.write(r+"<br/>"); break; } }
注:测试中排除了0.1、0.2这类无法精确表示的数,以及1.25这类其倒数0.8无法精确表示的数,确保x和y均满足精确表示的条件。
内容的提问来源于stack exchange,提问作者displaydisplayname
相关产品推荐
相关产品推荐

