Попробуйте выполнить следующую команду:
n = line number
tail -r file_name | sed '1,nd' | tail -r
Для управления точностью арифметики с плавающей точкой необходимо использовать java.math. BigDecimal. Читайте потребность в BigDecimal John Zukowski для получения дополнительной информации.
, Учитывая Ваш пример, последняя строка как следовала бы за использованием BigDecimal.
import java.math.BigDecimal;
BigDecimal premium = BigDecimal.valueOf("1586.6");
BigDecimal netToCompany = BigDecimal.valueOf("708.75");
BigDecimal commission = premium.subtract(netToCompany);
System.out.println(commission + " = " + premium + " - " + netToCompany);
Это приводит к следующему выводу.
877.85 = 1586.6 - 708.75
Как предыдущие указанные ответы, это - последствие выполнения арифметики с плавающей точкой.
Как предыдущий предложенный плакат, Когда Вы делаете числовые вычисления, использование java.math.BigDecimal
.
Однако существует глюк к использованию BigDecimal
. Когда Вы преобразовываете от двойного значения до BigDecimal
, у Вас есть выбор использования нового BigDecimal(double)
конструктор или BigDecimal.valueOf(double)
статический метод фабрики. Используйте статический метод фабрики.
двойной конструктор преобразовывает всю точность double
к BigDecimal
, в то время как статическая фабрика эффективно преобразовывает ее в String
, затем преобразовывает это в BigDecimal
.
Это становится релевантным при столкновении с теми тонкими погрешностями округления. Число могло бы отобразиться как.585, но внутренне его значение '0.58499999999999996447286321199499070644378662109375'. Если бы Вы использовали BigDecimal
конструктор, Вы получили бы число, которое не равно 0,585, в то время как статический метод дал бы Вам значение, равное 0,585.
double value = 0.585; System.out.println(new BigDecimal(value)); System.out.println(BigDecimal.valueOf(value));
в моей системе дает
0.58499999999999996447286321199499070644378662109375 0.585
Другой пример:
double d = 0;
for (int i = 1; i <= 10; i++) {
d += 0.1;
}
System.out.println(d); // prints 0.9999999999999999 not 1.0
Использование BigDecimal вместо этого.
РЕДАКТИРОВАНИЕ:
кроме того, только для указания это не проблема округления 'Java'. Другие языки показывают подобный (хотя не обязательно последовательный) поведение. Java, по крайней мере, гарантирует последовательное поведение в этом отношении.
Любое время, с которым Вы делаете вычисления, удваивается, это может произойти. Этот код дал бы Вам 877.85:
двойной ответ = Math.round (dCommission * 100000) / 100000.0;
Сохраните количество центов, а не долларов, и просто сделайте формат к долларам при выводе его. Тем путем можно использовать целое число, которое не страдает от проблем точности.
Посмотрите ответы на этот вопрос . По существу то, что Вы видите, является естественным следствием использования арифметики с плавающей точкой.
Вы могли выбрать некоторую произвольную точность (значащие цифры Ваших исходных данных?) и вокруг Вашего результата к нему, если Вы чувствуете себя комфортно, делая это.
Я бы изменил приведенный выше пример следующим образом:
import java.math.BigDecimal;
BigDecimal premium = new BigDecimal("1586.6");
BigDecimal netToCompany = new BigDecimal("708.75");
BigDecimal commission = premium.subtract(netToCompany);
System.out.println(commission + " = " + premium + " - " + netToCompany);
Таким образом, вы избежите ловушек использования строки для начала. Другая альтернатива:
import java.math.BigDecimal;
BigDecimal premium = BigDecimal.valueOf(158660, 2);
BigDecimal netToCompany = BigDecimal.valueOf(70875, 2);
BigDecimal commission = premium.subtract(netToCompany);
System.out.println(commission + " = " + premium + " - " + netToCompany);
Я думаю, что эти варианты лучше, чем использование двойных. В любом случае числа в веб-приложениях начинаются как строки.
Самый элегантный и эффективный способ сделать это на Java:
double newNum = Math.floor(num * 100 + 0.5) / 100;