C#中的双倍与十进制舍入
为什么:
double dividend = 1.0; double divisor = 3.0; Console.WriteLine(dividend / divisor * divisor); 输出1.0, 但: decimal dividend = 1; decimal divisor = 3; Console.WriteLine(dividend / divisor * divisor); 输出0.9999999999999999999999999999 ? 我知道1/3不能精确计算,因此必须进行一些舍入. 另外,为什么双倍计算1.0 / 3.0为0.33333333333333331? 解决方法
为什么1/3作为双倍是0.33333333333333331
在二进制中表示1/3的最接近的方式是这样的: 当然,这受到可以存储在双精度中的位数的限制.双精度是64位,但其中一个是符号位,另一个11代表指数(想象它像科学记数法,但是二进制).所以其余的,称为尾数或有效数是52位.假设1开始,然后对每个1/4的后续功率使用两个比特.这意味着你可以存储: 为什么乘以3轮到1轮 所以以二进制表示的1/3和受双精度大小限制的是: 让我们坚持使用这个“数学家的二进制”表示并忽略双精度的大小限制.你不必这样做,但我觉得很方便.如果我们想要将此近似值用于1/3并乘以3,则与将位移位乘以2然后添加开始时的值相同.这给了我们1/3 * 3 = 0.222222222222222222222222222222222222222222222222221111 但可以双重存储吗?不,请记住,在第一个1之后你只能有52位的尾数,而这个数字有54个.所以我们知道它会被舍入,在这种情况下四舍五入到1. 为什么小数点得到0.9999999999999999999999999999 使用十进制,你得到96位来表示一个整数,其他位表示指数高达28的10次幂.所以即使最终它都存储为二进制,这里我们使用10的幂,所以思考是有意义的基数为10. 96位允许我们表达高达79,228,162,514,264,337,593,543,950,335,但是为了代表1/3,我们将使用所有3,其中最多可以移动到小数点右边的28位: 0.3333333333333333333333333333. 将此近似值乘以1/3乘以3可得到一个我们可以准确表示的数字.它只是28 9,全部移到小数点右侧:0.999999999999999999999999999999.因此,与双重不同的是,此时不会进行第二轮舍入. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |