2012-08-05 4 views
4

Учитывайте, что налог на 10% распространяется на все предметы, кроме продуктов питания. Кроме того, дополнительный налог в размере 5% применим к импортируемым товарам.Лучший способ округления до ближайшего 0.05 в java

Если стоимость музыкального компакт-диска составляет 12,49. Налог на этот предмет будет 1,499. Если стоимость импортированной бутылки парфюма составляет 47,50, налог на товар будет 7,255

Существует политика, в которой говорится, что налоги на товар должны округляться до ближайшего 0,05. Поэтому 1.499 следует округлить до 1,5 и 7.125 следует округлить до 7,25.

выше округление Requirment может быть достигнуто с помощью логики:

(float) Math.ceil(taxAmount/0.05f) * 0.05f; 

Добавление налога в стоимости товара дает:

музыка CD: 12,49 + 1,5 = 13,99 импортирован коробка конфет : 47,50 + 7,25 = 54,65.

Я столкнулся с проблемой для следующего ввода:

Если стоимость импортируемых коробков конфет является 11,85, налог будет 0.5925

Используя округление политика, налог после округления будет 0.6.

Когда мы добавляем 11.85 + 0.6, которые являются поплавками, получаем результат как 12.450001. В отличие от других входов, этот конкретный вход дает много десятичных знаков, а не 2 десятичных разряда на других выходах.

Я попытался использовать BigDecimal вместо float, чтобы сохранить все значения с шкалой, установленной на 2 десятичных знака. Проблема с этим подходом заключается в том, что bigDecimal будет генерировать исключение для некоторых случаев, если политика округления не указана. Предоставление политики округления для BigDecimal приводит к тому, что общая сумма стоимости предмета и применимого налога округляется с использованием политики округления, предоставляемой BigDecimal, таким образом изменяя требуемый результат.

+1

Re: Ваша «проблема» с BigDecimal, да, цель обеспечения политики округления заключается в том, что она должна использоваться. И, очевидно, это изменит результат. Вероятно, ваша проблема связана с политикой WRONG. –

+0

AFAIK, ни одна из политик, предоставляемых BigDecimal, не будет соответствовать моему требованию. – CKing

+1

Вы используете правильное масштабирование? Если да, то один из режимов ROUND_HALF_XXX - это то, что вы хотите. –

ответ

7

Вы можете использовать long вместо double использовать два раза вы можете сделать

double d = Math.round(d * 20)/20.0; // round up to multiple of 0.05 

использовать длинные (как центов)

long l = (l + 3)/5 * 5; 

Хотя его часто считается наилучшей практикой использования int, long или BigDecimal большинство инвестиций банки и фонды используют double, потому что как только вы поймете, как их безопасно использовать, они проще (чем длиннее) и быстрее (чем BigDecimal).

+0

Как конвертировать назад из long в float и узнать точное место, где положить десятичную точку? Выход должен отображаться десятичным и недолго. – CKing

+0

Я бы сделал предположение, что в долларе стоит 100 центов. то есть деление на 100,0 до начала печати. Лично у меня нет проблемы с использованием double. Я бы не использовал 'float', если на самом деле нет выбора. –

+0

Чтобы преобразовать десятичное значение в long или int, мне придется умножить его на 100? Что делать, если после десятичной запятой есть более двух цифр по цене товара? – CKing

3

Храните денежные суммы в виде целых чисел (например, количество центов).

Это распространенная проблема - Google предоставит вам много замечательных объяснений.

Вот один: Why not use Double or Float to represent currency?

+1

Это было бы скорее ответом, чтобы сказать, как это сделать. В противном случае это скорее комментарий. –

+0

Как это сделать? Как использовать целое число для хранения денежных сумм? – John3136

+0

Как «Лучший метод округления до ближайшего 0.05 в java» –

0

Это, похоже, является частью известной проблемы интервью с технологией. Цель состоит в том, чтобы понять, что вам нужно рассчитать налоги и округлить эту сумму до верхнего 0.05 для расчета округления я использовал этот Groovy скрипт

import java.math.* 

def myRound(BigDecimal d){ 
    def scale = new BigDecimal("0.05") 
    def y = d.divide(scale) 
    println "y :$y" 
// def q = y.round(new MathContext(0,RoundingMode.UP)) 
    def q = y.setScale(0,BigDecimal.ROUND_UP) 
    println "q :$q (intero)" 
    def z = q.multiply(scale) 
    println "z :$z" 
    return z 
} 

def taxBy(BigDecimal d,BigDecimal t){ 
    return myRound(d.multiply(t)) 
} 
def importTax(BigDecimal d){ 
    return taxBy(d,new BigDecimal("0.15")) 
} 

def importBaseTax(BigDecimal b){ 
    return taxBy(d,new BigDecimal("0.05")) 
} 

ip = new BigDecimal("27.99") 
ipt = importTax(ip) 

println "${ip}-->${ipt} = ${ip+ipt}" 

Я надеюсь, что это будет полезно!

Смежные вопросы