Я перевожу приложение 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 ?)
ОБНОВИТЬ:
Макс Зум Спасибо. Ваш тест работает отлично.
Но в моем коде я получаю значения из БД, определенные как:
@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
Если вы хотите использовать собственное округление:
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);
}
Я удалил свое решение, так как оно было неверным. Но я приведу объяснение не столь очевидного поведения округления 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 заданные двойные значения точны, а режим округления также равен половине.
5.0500000000000000 5.0
5.1500000000000000 5.2
5.2500000000000000 5.2
5.3500000000000000 5.4
5.4500000000000000 5.4
5.5500000000000000 5.6
Эквивалент в Java:
System.out.printf("%3.1f", 5.05); // 5.1
System.out.printf("%.1f", insertFloatValueHere);
автоматически округляется до десятых
если вы хотите изменить количество десятичных разрядов, которое оно округляет до:
"%.1f"
раунды в одно место
"%.2f"
туры в два места
"%.3f"
туры в три места … и т. д.
System.out.printf("%.1f", dArr[i]);
заменяет:
sprintf(result,"%3.1lf",dArr[i]);
cout << result << endl;