在Java中舍入?

Rounding in Java?

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

我的任务如下:

将20对数字(分别是ID号和分数)读取到两个单独的数组中。找出平均分数。打印下表所示的每个学生的ID、分数和差异(分数-平均值),每行一名学生。如图所示,打印表头的总分、平均分和计分。将平均值和差四舍五入到小数点后两位。

我的程序中有一个非常简单的bug,但我只是因为某些原因无法解决它。我已经知道怎么做了,但是由于某种原因,我的减法被取消了。以下是示例输出供参考:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ID  Score   Difference
115 257.0   14.349999999999994
123 253.0   10.349999999999994
116 246.0   3.3499999999999943
113 243.0   0.3499999999999943
112 239.0   -3.6500000000000057
104 239.0   -3.6500000000000057
110 238.0   -4.650000000000006
218 243.0   0.3499999999999943
208 242.0   -0.6500000000000057
222 223.0   -19.650000000000006
223 230.0   -12.650000000000006
213 229.0   -13.650000000000006
207 228.0   -14.650000000000006
203 224.0   -18.650000000000006
305 265.0   22.349999999999994
306 262.0   19.349999999999994
311 256.0   13.349999999999994
325 246.0   3.3499999999999943
321 245.0   2.3499999999999943
323 245.0   2.3499999999999943

问题是,当我调用我的程序只是打印它计算的平均值时,它是一个很好的四舍五入242.65。既然分数也是一个整数,我不明白这是怎么回事?你能不能解释一下这里出了什么问题?

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import java.util.Scanner;
import java.io.*;

public class prog402a
{
    public static void main(String args[])
    {
        Scanner inFile = null;
        try
        {
            inFile = new Scanner(new File("prog402a.dat"));
        }
        catch (FileNotFoundException e)
        {
            System.out.println("File not found!");
            System.exit(0);
        }

        int[] idNumber = new int[20];
        double[] score = new double[20];

        for(int k = 0; k < idNumber.length; k++)
        {
            idNumber[k] = inFile.nextInt();
            score[k] = inFile.nextDouble();
        }

        double sum = 0;

        for(int k = 0; k < score.length; k++)
        {
            sum += score[k];
        }

        double doubSum = (double)sum;
        double average = doubSum/20.0;
        average=(int)(average*100+.5)/100.0;
        System.out.println(average);

        System.out.println("ID\tScore\tDifference");
        for(int k = 0; k < idNumber.length; k++)
        {
            System.out.println(idNumber[k] +"\t" + score[k] +"\t" + (score[k] - average));
        }



        inFile.close();

    }
}


浮点数(例如爪哇中的浮点数和双数)编程语言和数学语言一样有100%的精度。

所以很可能是一个很好的整数(十进制),比如

二百四十二点六五

内部(在JVM中,例如)表示为242.6499999997。

我只是粗略地说了一下,但你明白了。

在打印每个数字之前,只需将其格式化为第二个十进制数字,就可以了。让我试着为您编写一个小示例…这里是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.text.DecimalFormat;
import java.text.NumberFormat;

public class Test020 {

    public static void main(String[] args) {

        double d = 13.5 + 0.1 + 0.11;

        System.out.println(d);

        NumberFormat formatter = new DecimalFormat("#0.00");    
        System.out.println(formatter.format(d));

    }

}


浮点使用二进制系统来表示数字。这意味着在十进制系统中可以用有限位数表示的一些数字在二进制系统中是不可能的。例如,无法正确表示0.2二进制文件。因此,该算法将使用它能表示的最接近的值。因此,它将与0.199999...ish或0.2000...1ish一起工作。注意,十进制系统也有问题,例如表示1/3是用0.333333....来完成的,所以如果用有限的数字来计算的话。你总是会犯(小)错误。

然而,有一个班级——BigDecimal能够以任意精度计算分数,尽管我认为计算20学生的平均分只会在7左右的数字上有所不同。

因此,我建议简单地格式化这些数字,例如,它将结果精确地显示在两位数字上。您可以使用以下方法进行此操作:

1
2
3
DecimalFormat myFormatter = new DecimalFormat("0.000"); //the pattern
String output = myFormatter.format(number);
System.out.println(output);


如前所述,问题在于浮动不是100%准确。最简单的解决方案可能是string.format;将打印行更改为:

1
2
 System.out.println(
     String.format("%d\t%.2f\t%.2f", idNumber[k], score[k], score[k] - average));

这将输出四舍五入到小数点后2位的数字。