2

-0.123e-35例如,我们从之前的计算中得到一个非常非常小的负数。该数字可用于其他一些公式。将这个数字四舍五入假设小数点后十位为零'0'是正确的方法吗?如果这个数字只用于加法运算是可以的,但它会在乘法运算中给出错误的结果。如何正确地做到这一点?

UPD

为什么需要我?我在矩阵上实现了 DCT 方法。在由“1”填充的测试矩阵 8x8 上。我明白了:

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.

如您所见,只有零。我想了解我可以将那些非常小的负数四舍五入为零吗?

4

5 回答 5

3

这里有很多答案建议您按照(x * 10^n) / 10^n. 但是,这通常不会四舍五入到n小数位。

二进制浮点不能精确表示大多数有限十进制值,例如 0.1 实际上是0.100000001490116 ... 它只会为您提供与您的目标最接近的可代表价值。对于精确的表示,您需要调查一个BigDecimal库/类(其详细信息因语言而异)。

但是,如果您只想将值显示到小数点后 10 位,那么您的语言可能会提供类似于 C 的内容printf("%.10f\n", x);。出于显示目的,这确实会四舍五入到小数点后 10 位。


* 请参阅http://floating-point-gui.de/了解初学者对这个重要问题的介绍。

于 2013-06-12T01:09:14.883 回答
1

您所显示的信息不能证明需要四舍五入为零。最有可能的是,您应该简单地忽略某些结果很小的事实并继续正常工作。

完美的测试数据并不能很好地证明 DCT。现实世界的数据很少会导致 DCT 的值恰好为零。此外,如果您将 DCT 应用于现实世界的数据并获得一个很小的值,它可能会很小,因为这是数学上正确的结果,或者因为数学上正确的结果为零但存在一些错误。这意味着您将无法确定是否应将 DCT 结果中的小值更正为零或保持不变。因此,尝试将值更改为零实际上会使数据变得更糟。

此外,较小的值不太可能影响工作。您的应用程序将使用 DCT 的结果来修改或分析信号,然后继续执行逆变换或以其他方式使用结果。通常,这种进一步的使用不会受到数据中存在的微小错误的显着影响。(来自麦克风或其他传感器或环境噪声的误差可能大于这些误差。)

换句话说,这些小值只会困扰您,即人类,而不是计算机。别理他们。

于 2013-06-12T16:15:43.153 回答
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,我认为这就是您要寻找的。

如果小于 0.00000000005,则可能比舍入所有数字更好地解决您的问题

if (num < 0.00000000005) num = 0;
于 2013-06-12T00:41:41.057 回答
0

在python中这是

round(n*(1e10))/(1e10)
于 2013-06-12T00:47:37.617 回答
0

舍入到小数点后 N 位的最简单方法是使用舍入,注意这会返回 a long,因此您必须除以一个双精度值,否则您可以获得整数除法。

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;
}

在这里,我使用了铸造而不是四舍五入,因为它几乎一样准确但速度更快。

于 2013-06-12T00:50:21.310 回答