gpt4 book ai didi

java - 如何克服 Java 中的不准确问题

转载 作者:行者123 更新时间:2023-12-02 08:56:49 25 4
gpt4 key购买 nike

当我执行以下程序时,我开始了解准确性问题:

public static void main(String args[])
{
double table[][] = new double[5][4];
int i, j;
for(i = 0, j = 0; i <= 90; i+= 15)
{
if(i == 15 || i == 75)
continue;
table[j][0] = i;
double theta = StrictMath.toRadians((double)i);
table[j][1] = StrictMath.sin(theta);
table[j][2] = StrictMath.cos(theta);
table[j++][3] = StrictMath.tan(theta);
}
System.out.println("angle#sin#cos#tan");
for(i = 0; i < table.length; i++){
for(j = 0; j < table[i].length; j++)
System.out.print(table[i][j] + "\t");
System.out.println();
}
}

输出是:

angle#sin#cos#tan
0.0 0.0 1.0 0.0
30.0 0.49999999999999994 0.8660254037844387 0.5773502691896257
45.0 0.7071067811865475 0.7071067811865476 0.9999999999999999
60.0 0.8660254037844386 0.5000000000000001 1.7320508075688767
90.0 1.0 6.123233995736766E-17 1.633123935319537E16

(请原谅无组织的输出)。我注意到了几件事:

  • sin 30 即 0.5 存储为 0.49999999999999994
  • tan 45,即 1.0 存储为 0.9999999999999999
  • tan 90,即无穷大未定义存储为1.633123935319537E16(这是一个非常大的数字)。

当然,我对看到输出感到非常困惑(即使在破译了输出之后)。

所以我读过this帖子,最佳答案告诉我:

These accuracy problems are due to the internal representation of floating > point numbers and there's not much you can do to avoid it.

By the way, printing these values at run-time often still leads to the correct results, at >least using modern C++ compilers. For most operations, this isn't much of an issue.

answered Oct 7 '08 at 7:42

Konrad Rudolph

所以,我的问题是:

有什么方法可以防止这种不准确的结果(在 Java 中)?

我应该对结果进行四舍五入吗?在这种情况下,我将如何存储无穷大,即Double.POSITIVE_INFINITY

最佳答案

您必须对 float 采取一些 zen* 方法:与其消除错误,不如学会忍受它。

实际上,这通常意味着执行以下操作:

  • 显示号码时,使用 String.format指定要显示的精度(它会为您进行适当的舍入)
  • 与预期值进行比较时,不要寻找相等性 ( == )。相反,寻找足够小的增量:Math.abs(myValue - expectedValue) <= someSmallError

编辑:对于无穷大,同样的原则适用,但有一些调整:您必须选择一些“足够大”的数字来视为无穷大。这又是因为你必须学会​​忍受而不是解决不精确的值(value)观。对于 tan(90 度) 之类的情况, double 无法以无限精度存储 π/2,因此您的输入非常接近但不完全是 90 度 - 因此,结果是非常接近的大,但不是无限大。您可能会问“当您传递最接近 π/2 的 double 值时,为什么它们不直接返回 Double.POSITIVE_INFINITY”,但这可能会导致歧义:如果您确实想要该数字的 tan,而不是 90 度,该怎么办?或者,如果(由于之前的浮点错误)您有比最接近的可能值距离 π/2 稍远的值,但根据您的需要,它仍然是 π/2,该怎么办? JDK 不会为您做出任意决定,而是按表面值处理接近但不精确的 π/2 数字,从而为您提供一个大但不无穷大的结果。

对于某些操作,尤其是与金钱相关的操作,您可以使用 BigDecimal消除浮点错误:您可以真正表示像 0.1 这样的值(而不是真正接近 0.1 的值,这是 float 或 double 可以做到的最好的值)。但这要慢得多,并且对 sin/cos 之类的事情没有帮助(至少对于内置库而言)。

*这可能不是真正的禅宗,而是口语意义上的

关于java - 如何克服 Java 中的不准确问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22189081/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com