关于java:数组中奇怪的双重打印

Weird double printing in array

本问题已经有最佳答案,请猛点这里访问。

我正在编写一个程序,它打印一个数组,其中包含作为参数传递的两个数组的值之和。除了最后一个双精度值外,它都可以正常工作。我希望最后一个值打印为3.1。而是打印以下内容:

[5.9,11.7,2.4,3.099999999996]

不知道如何格式化打印,否则不允许使用字符串来解决问题。我对其他价值观没有这个问题。这是我的密码,谢谢你的帮助!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    import java.util.*;

class Sum
{
    public static void main (String [] args)
    {
        double [] a1 = {4.5, 2.8, 3.4, 0.8};
        double [] a2 = {1.4, 8.9, -1.0, 2.3};

        arraySum (a1, a2);

        System.out.println (Arrays.toString (arraySum (a1, a2)));  
    }

    public static double [] arraySum (double [] x, double [] y)
    {
        int length = 0;
        double [] sum = new double [x.length];
        length = x.length;

            for (int i = 0; i <= length - 1; i++)
            {
                sum[i] = x[i] + y[i];
            }

        return sum;

    }
}


这是由于IEEE浮点模型。它不能准确地表示3.1。要想按您的要求打印,您必须手动打印,而不是使用Arrays.toString。循环双打并格式化它们:

1
2
3
4
5
6
7
8
9
10
11
12
13
public static String toString(double[] x, DecimalFormat format)
{
    StringBuilder sb = new StringBuilder();
    sb.append("[");
    for (int i = 0; i < x.length; ++i)
    {
        sb.append(format.format(x[i]));
        sb.append(",");
    }
    sb.delete(sb.length() - 2, sb.length());
    sb.append("]");
    return sb.toString();
}

然后像这样叫:

1
toString(sum, new DecimalFormat("#.#"));

要仅使用双打来完成此技巧,您可能会尝试应用此技巧,但这很脏,不能保证有效:

1
2
3
double x = ...;
x = 0.001 * Math.round(x * 1000.0);
System.out.println(x);


您要使用decialm格式

1
2
DecimalFormat df=new DecimalFormat("#.#");
String outputString=df.format(sum);


如果不允许使用System.out.printf()来解决问题,那么您唯一的选择就是使用BigDecimal对象来保存值。如果没有这两种方法中的一种(或DecimalFormat),您将无法从double中得到3.1结果。

你说你"不能用弦来解它",但我不认为这样做…

1
2
3
4
for (double d : arraySum (a1, a2)) {
    System.out.printf("%.1f
"
, d);
}

限定为"使用字符串来解决它"。在我看来完全合法。


如果您四舍五入到一个合理数量的sigfig,这个数字仍然是正确的,这就是decimalformat和string.format在封面下对您的作用。正如NeMeNIM所说的,这是由Java程序中奇怪的浮点行为引起的同样问题引起的。如果你真的觉得实际的数字精确到sigfigs-~8比考虑使用bigdecimal更重要,因为你永远不会失去任何精度。