我们从之前的计算中获得了一个非常小的负数,例如-0.123e-35
。
该数字可用于其他一些公式中。是否正确的方法将这个数字舍入到十个小数位为零'0'?
如果这个数字仅用于加法运算,但在乘法运算中会产生错误的结果,这是可以的。
如何正确地做到这一点?
UPD
为什么需要我?我在矩阵上实现了DCT方法。在测试矩阵8x8上填充'1'。我明白了:
8 -7.49778027488703e-13 7.64321008887262e-13 -7.90698562193149e-13 8.26182651759402e-13 -8.78937758371177e-13 9.51152198392764e-13 -1.04158952401295e-12
-7.51721016906324e-13 1.66533453693773e-16 -2.77555756156289e-17 2.77555756156289e-17 2.77555756156289e-17 2.77555756156289e-17 -2.77555756156289e-17 1.38777878078145e-17
7.65773344411544e-13 2.77555756156289e-17 -1.38777878078145e-16 -2.77555756156289e-17 0 0 0 -1.38777878078145e-17
-7.91522860733958e-13 0 5.55111512312578e-17 -5.55111512312578e-17 -2.77555756156289e-17 -2.77555756156289e-17 -1.38777878078145e-17 -1.38777878078145e-17
8.26025642513534e-13 8.32667268468867e-17 -2.77555756156289e-17 0 0 5.55111512312578e-17 -6.93889390390723e-17 -6.93889390390723e-18
-8.78466730633572e-13 8.32667268468867e-17 -2.77555756156289e-17 -4.16333634234434e-17 1.11022302462516e-16 4.16333634234434e-17 -1.38777878078145e-17 5.55111512312578e-17
9.50946123757562e-13 -1.66533453693773e-16 -9.71445146547012e-17 2.77555756156289e-17 -9.71445146547012e-17 -1.38777878078145e-17 1.38777878078145e-17 -1.73472347597681e-17
-1.04131475783268e-12 -8.32667268468867e-17 4.16333634234434e-17 -4.16333634234434e-17 -1.38777878078145e-17 5.55111512312578e-17 2.77555756156289e-17 -4.16333634234434e-17
我也做同样的事情,但在Scilab中,它给了我这个:
8. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
如你所见,只有零。而且我想理解我可以将这些非常小的负数舍入到零或不是吗?
答案 0 :(得分:3)
这里有很多答案,建议你按照(x * 10^n) / 10^n
的方式做一些事情。但是,通常情况下,不舍入到n
小数位。
二进制浮点不能精确地表示大多数有限的十进制值,例如0.1实际上是0.100000001490116 ... * 因此,如果您的目标是获得有限十进制扩展的精确表示(对于后续计算),这种方法不起作用;它只会为您提供最接近的可表示值。要获得精确的表示,您需要调查BigDecimal
库/类(其详细信息因语言而异)。
但是,如果您只想显示值到10位小数,那么您的语言可能会提供与C printf("%.10f\n", x);
类似的内容。为了显示目的,这实际上将舍入到10个小数位。
<小时/> *有关此重要问题的初学者介绍,请参阅http://floating-point-gui.de/。
答案 1 :(得分:1)
要在JavaScript中舍入到10个小数位(因为问题最初被标记),只需执行以下操作。
var num = 0.0000000000000000000000000000000000123; // 1.23e-35
num = Math.round(num * 10000000000) / 10000000000; // 0
var num = 0.000000000123; // 1.23e-10
num = Math.round(num * 10000000000) / 10000000000; // 1e-10
请注意,虽然上述结果会产生您正在寻找的结果,但浮点值不是真正的十进制值,并且在某些情况下尝试“舍入”它们可能会产生意外结果。但是,此解决方案将确保将小于0.00000000005的任何数字舍入为0,我认为这正是您要寻找的。 p>
对于您的问题,可能比舍入所有数字更好的解决方案将有条件地将值设置为0,如果它是&lt; 0.00000000005
if (num < 0.00000000005) num = 0;
答案 2 :(得分:1)
您所显示的信息并不能证明任何需要舍入为零的理由。最有可能的是,您应该忽略这样一个事实,即某些结果很小并继续正常工作。
完美的测试数据不是DCT的良好示范。实际数据很少会产生具有正好零值的DCT。此外,如果将DCT应用于实际数据并获得较小的值,则可能很小,因为这是数学上正确的结果,或者因为数学上正确的结果将为零但是存在一些错误。这意味着您无法确定DCT结果中的较小值是应该更正为零还是单独保留。因此,尝试将值更改为零实际上可能会使数据变得更糟。
此外,小值不太可能影响工作。您的应用程序将使用DCT的结果来修改或分析信号,然后继续执行逆变换或以其他方式使用结果。通常,这种进一步的使用不会受到数据中微小错误的显着影响。 (麦克风或其他传感器的误差或环境噪声可能比这些误差大。)
换句话说,这些小小的价值只会困扰你,人类,而不是计算机。忽略它们。
答案 3 :(得分:0)
在python中这是
round(n*(1e10))/(1e10)
答案 4 :(得分:0)
舍入到N个小数位的最简单方法是使用round,请注意这将返回long
,因此您必须除以double值,否则可以得到整数除法。
double rounded = Math.round(d * 1e10) / 1e10;
使用1eN表示法可以更清楚地了解您想要舍入的数字。为确保不溢出,您需要进行边界检查。
public static double round10(double d) {
final double factor = 1e10;
return d > Long.MAX_VALUE / factor || d < -Long.MAX_VALUE / factor ?
(long) (d < 0 ? d * factor - 0.5 : d * factor + 0.5) / factor : d;
}
这里我使用的是铸造而不是圆角,因为它几乎同样准确但更快。