【发布时间】:2023-12-22 02:05:02
【问题描述】:
我需要对双精度数的有效数字进行舍入。例子 Round(1.2E-20, 0) 应该变成 1.0E-20
我不能使用返回 0 的 Math.Round(1.2E-20, 0),因为 Math.Round() 不会将浮点数中的有效数字四舍五入,而是舍入十进制数字,即 E 为 0 的双精度数。
当然,我可以这样做:
double d = 1.29E-20;
d *= 1E+20;
d = Math.Round(d, 1);
d /= 1E+20;
这确实有效。但这不是:
d = 1.29E-10;
d *= 1E+10;
d = Math.Round(d, 1);
d /= 1E+10;
在这种情况下,d 为 0.00000000013000000000000002。问题是 double 在内部存储 2 的小数,它不能完全匹配 10 的小数。在第一种情况下,C# 似乎只处理 * 和 / 的指数,但在第二种情况下,它会生成一个实际的 * 或/操作,然后会导致问题。
当然,我需要一个总能给出正确结果的公式,不仅仅是有时。
意思是我不应该在舍入后使用任何双精度运算,因为双精度运算不能完全处理小数。
上面计算的另一个问题是没有返回双精度指数的双精度函数。当然可以使用 Math 库来计算它,但可能很难保证它总是与 double 内部代码完全相同。
在我绝望中,我考虑将双精度数转换为字符串,找到有效数字,进行舍入并将舍入的数字转换回字符串,然后最后将其转换为双精度数。丑陋,对吧?在所有情况下也可能无法正常工作:-(
是否有任何库或任何建议如何正确舍入双精度数的有效数字?
PS:在声明这是一个重复的问题之前,请确保您了解重要数字和小数位之间的区别
【问题讨论】:
-
“2 的分数”是指“2 的因数”吗?
-
不要使用
double,不如使用Decimal。 -
十进制显着慢,但更准确。还取决于您需要的值的范围。
-
那些将此问题标记为重复的人,能否请他们提供指向他们认为相同的问题的链接。我在*上经历了数百个四舍五入的问题。我找不到有人问我的问题,我很乐意获得链接。
-
我不能使用小数,因为我用双精度写了一个图表。它涵盖了整个双范围。它还支持缩放和滚动,如果舍入错误,这会导致标签和网格线出现各种可见的问题。