当前位置: 首页 > 面试题库 >

如何克服Java中的不准确性

田志尚
2023-03-14
问题内容

当我执行以下程序时,我就知道了 精度问题

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
  • 棕褐色45即1.0存储为0.9999999999999999
  • tan 90即infinityundefined存储为1.633123935319537E16(这是一个非常大的数字)。

自然,我很困惑地看到输出(即使在解密输出之后)。

所以我读了这篇文章,最佳答案告诉我:

这些精度问题是由于浮点数>点号的内部表示而引起的,您无法做很多事情来避免这种情况。

顺便说一下,使用现代C ++编译器至少在运行时打印这些值通常仍会得到正确的结果。对于大多数操作而言,这并不是什么大问题。

2008年10月7日在7:42回答

康拉德·鲁道夫

所以,我的问题是:

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

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


问题答案:

对于浮点数,您必须采取zen *的方法:与其消除错误,不如从容应对。

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

  • 在显示数字时,用于String.format指定要显示的精度(它将为您进行适当的舍入)
  • 与预期值进行比较时,请勿寻找相等(==)。而是寻找一个足够小的增量:Math.abs(myValue - expectedValue) <= someSmallError

编辑
:对于无穷大,相同的原理适用,但是要进行一些调整:您必须选择一些数字以“足够大”以将其视为无穷大。再次是因为您必须学会忍受而不是解决不精确的价值观。在诸如tan(90度)之类的情况下,双精度不能以无限的精度存储π/
2,因此您输入的内容非常接近但不完全是90度,因此结果是大,但不是无限。您可能会问“为什么Double.POSITIVE_INFINITY当您传递最接近π/
2的双精度数时,它们为什么不html" target="_blank">返回”,但这可能会导致模棱两可:如果您真的想要该数字的正切而不是90度,该怎么办?或者,如果(由于以前的浮点错误),你有什么东西是
略有 比最接近的值离π/ 2更远,但对于您的需求,它仍然是π/ 2?JDK不会为您做出任意决定,而是会以您的票面价值来对待您接近但并非完全是π/
2的数字,从而为您带来一个大但并非无限的结果。


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

*这实际上可能不是禅宗,但在口语上



 类似资料:
  • 克隆当前板 采取行动 查看移动玩家是否处于检查中 如有,则不允许移动;否则,允许移动 我从这里获得关于如何克隆的提示: 现在,board对象由一个2D方形对象数组组成。每个方形对象都有一个piece字段,该字段要么为null(上面没有piece),要么引用一个piece对象(上面有一个piece)。board对象还有一个whiteKingSquare和一个blackKingSquare(都是方形对

  • 当我的应用程序安装到Android L preview时,它会失败,出现错误: install_failed_no_matching_abis。 我的应用程序只使用arm库,使用库的功能在x86上被禁用。它在Android L之前工作得很完美,但现在我连它都装不上了。如何为我的应用程序禁用此错误?

  • 问题内容: 我正在尝试通过React应用程序中的Axios进行API调用,但是我在浏览器中遇到了CORS问题。我想知道我是否可以从客户端解决此问题,因为我内部没有对API的任何访问权。附加的是我的代码。 附件是我的WebPack.config.js 问题答案: 理想的方法是向服务器添加CORS支持。 您也可以尝试使用单独的jsonp模块。据我所知axios不支持jsonp。因此,我不确定您使用的方

  • 我正在尝试通过我的React应用程序中的Axios进行API调用。但是,我在浏览器上遇到了这个CORS问题。我想知道我是否可以从客户端解决这个问题,因为我在内部没有任何对API的访问权限。附件是我的代码。 附件是我的WebPack.config.js

  • 问题内容: 我需要在我的没有超类的对象中实现一个深层克隆。 处理超类(即)引发的检查的最佳方法是什么? 一位同事建议我按以下方式处理: 对我来说,这似乎是一个不错的解决方案,但我想将其扔给StackOverflow社区,以查看是否有我可以提供的其他见解。 问题答案: 你绝对必须使用吗?大多数人都同意是坏的。 如果你已经阅读了我书中有关克隆的内容,尤其是你在两行之间阅读的话,你会知道我认为它clon

  • 刚刚开始使用scala和spark来运行这个简单的程序: