我正在将C ++应用程序迁移到Java。如何匹配sprintf的舍入行为?
int main() {
char result[20];
double dArr [6] = {5.05, 5.15, 5.25, 5.35, 5.45, 5.55};
for(int i; i< 6; i++) {
sprintf(result,"%3.1lf",dArr[i]);
cout << result << endl;
}
return 0;
}
VALUE C++ sprintf Rounding:
--------- ----------------------------------------
5.05 - 5.0 (rounding: half_down or half_even?)
5.15 - 5.2 (rounding: half_up or half_even?)
5.25 - 5.2 (rounding: half_down or half_even?)
5.35 - 5.3 (rounding: half_down or half_odd ?)
5.45 - 5.5 (rounding: half_up or half_odd ?)
5.55 - 5.5 (rounding: half_down or half_odd ?)
更新
Max Zoom谢谢。你的测试工作完美。
但在我的代码中,我将DB的值定义为:
@Column(precision=3, scale=2) //Oracle: CLASSAVERAGE NUMBER(3,2)
private BigDecimal classaverage;
当我尝试将数字四舍五入到BigDecimal.ROUND_HALF_EVEN时:
System.out.println(getClassaverage() + " - " + getClassaverage().setScale(1,BigDecimal.ROUND_HALF_EVEN) );
我得到了值"5.55" rounded to "5.6".
在我修改了测试后,我明白为什么会发生这种情况:
@Test
public void main() {
double [] dArr = {5.05, 5.15, 5.25, 5.35, 5.45, 5.55};
for (double d : dArr) {
System.out.println(new BigDecimal(d) + " - " + new BigDecimal(d).setScale(1, BigDecimal.ROUND_HALF_EVEN));
}
}
这就是我得到的:
5.04999999999999982236431605997495353221893310546875 - 5.0
5.1500000000000003552713678800500929355621337890625 - 5.2
5.25 - 5.2
5.3499999999999996447286321199499070644378662109375 - 5.3
5.45000000000000017763568394002504646778106689453125 - 5.5
5.54999999999999982236431605997495353221893310546875 - 5.5
当我将double[]
替换为String[]
时,您的测试会生成BigDecimal.ROUND_HALF_EVEN
的预期值:
5.05 - 5.0
5.15 - 5.2
5.25 - 5.2
5.35 - 5.4
5.45 - 5.4
5.55 - 5.6
答案 0 :(得分:5)
如果您想使用自己的四舍五入:
import java.math.BigDecimal;
public class BigDecimalFormat
{
private static int ROUNDING_MODE = BigDecimal.ROUND_HALF_EVEN;
private static int DECIMALS = 1;
public static void main(String[] args) {
double[] dArr = {5.05, 5.15, 5.25, 5.35, 5.45, 5.55};
for (double d : dArr)
System.out.println(rounded(new BigDecimal(d)));
}
public static BigDecimal rounded(BigDecimal number){
return number.setScale(DECIMALS, ROUNDING_MODE);
}
}
您希望格式化货币编号:
public static String currencyFormat(BigDecimal n) {
return NumberFormat.getCurrencyInstance().format(n);
}
答案 1 :(得分:2)
我删除了我的解决方案,因为它错了。但是我会解释C ++舍入的不那么明显的行为。
使用此C ++代码显示双打的内部值。
int main() {
char result[20];
double dArr [6] = {5.05, 5.15, 5.25, 5.35, 5.45, 5.55};
for(int i = 0; i< 6; i++) {
sprintf(result, "%3.16f %3.1lf", dArr[i], dArr[i]);
cout << result << endl;
}
return 0;
}
结果显示四舍五入总是一半。
5.0499999999999998 5.0
5.1500000000000004 5.2
5.2500000000000000 5.3
5.3499999999999996 5.3
5.4500000000000002 5.5
5.5499999999999998 5.5
我的初步修改建议
double[] dArr = {5.05, 5.15, 5.25, 5.35, 5.45, 5.55};
DecimalFormat df = new DecimalFormat("###.0");
for (double d : dArr) {
System.out.printf("%.16f %s%n", d, df.format(d));
}
显示在Java中,给定的double值是精确的,舍入模式也是一半甚至。
5.0500000000000000 5.0
5.1500000000000000 5.2
5.2500000000000000 5.2
5.3500000000000000 5.4
5.4500000000000000 5.4
5.5500000000000000 5.6
答案 2 :(得分:0)
Java中的等价物:
System.out.printf("%3.1f", 5.05); // 5.1
答案 3 :(得分:-1)
System.out.printf("%.1f", insertFloatValueHere);
自动舍入到最接近的第十个
如果你想改变它舍入的小数位数:
"%.1f"
轮到一个地方
"%.2f"
轮到两个地方
"%.3f"
轮到三个地方......等等。
System.out.printf("%.1f", dArr[i]);
取代:
sprintf(result,"%3.1lf",dArr[i]);
cout << result << endl;