我正在创建一个应用程序来计算百分比的平均值,但问题是BigDecimal并不总是舍入平均值,例如,如果标记平均值为3.85,则比例1中的BigDecimal ROUND_HALF_UP应该舍入到3.9但它显示平均值像3.8一样,只发生了一些特定的时间,有时BigDecimal像4.5一样4.95它的好,但我不知道为什么会发生,问题出在哪里。这是一个示例代码,您可以看到问题:
import java.io.*;
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) throws IOException{
InputStreamReader input = new InputStreamReader(System.in);
BufferedReader buff = new BufferedReader (input);
//temporal
float average=0;
float mark1=0;
float mark2=0;
float percent1=0.75f;
float percent2=0.25f;
for(int i=0;i<1;i++){
System.out.println("Enter mark 1 (75%) : ");
mark1=Float.parseFloat(buff.readLine());
}
for(int i=0;i<1;i++){
System.out.println("Enter mark 2 (25%): ");
mark2=Float.parseFloat(buff.readLine());
}
average= ((mark1*percent1)+(mark2*percent2));
// convert to BigDecimal
BigDecimal bd = new BigDecimal(average);
BigDecimal roundingMark = bd.setScale(1,
BigDecimal.ROUND_HALF_UP);
System.out.println(" the complete average is :"+average);
System.out.println(" The rounding average is :"+roundingMark);
}
}
你应该在第一个标记4.5和第二个标记1.9中输入结果为3.8并且应该是3.9
请原谅我的英语不好,非常感谢阅读:)
答案 0 :(得分:2)
您应该使用BigDecimal
进行计算,而不仅仅是舍入。
含义,mark1
,mark2
,percent1
,percent2
和average
应为BigDecimal
s。您在此处遇到的问题是precision problem:float
s不够精确,无法保证计算的准确性,因此您认为3.85
实际上应该是3.849999999999
。尝试打印bd
,您的原始值为849999904632568359375
(至少这是我的确切值)。
编辑,扩展:我刚刚想到你也可能误解了ROUND_HALF_UP的含义。我引用文档
舍入模式向&#34;最近邻居&#34;除非两个邻居都是等距的,在这种情况下会向上舍入。如果丢弃的分数≥0.5,则表现为ROUND_UP;否则,表现为ROUND_DOWN。请注意,这是我们大多数人在小学就读的四舍五入模式。
因此,总结精度问题,导致bd
的实际值更接近3.8
而不是3.9
,以及ROUND_HALF_UP
的预期行为,你应该现在有一个完整的结果解释。