2015-08-10 1 views
1

Есть ли способ, который я могу сравнить (>, <,> =, < =,! =, ==) десятичное число, представленное как long и int?Как сравнить десятичное число, представленное как long и int?

Если число 3214,21, то он будет представлен в классе, как этот

long units = 321421; 
int precision = 2; 
// to get the original number I would do units * 10^precision 

Я хотел бы быть в состоянии сделать что-то подобное() метод CompareTo BigDecimal в. Таким образом, больше, чем возвращает 1, равно возвращает 0, меньше, чем возвращает -1.

То, что я сейчас делаю, не работает для некоторых случаев. Код, который заставляет его функционировать таким образом, описан ниже. Этот метод является более или менее доказательством концепции.

public int compareTo(Money other) { 
    if (precision == other.getPrecision()) { // fast check if precision is the same 
     if (units > other.getUnits()) return 1; // we forgot to inverse/flip here. will be an issue for non-decimal 
     else if (units < other.getUnits()) return -1; 
     else return 0; // least likely 
    } 

    int intX = (int) (units/(Math.pow(10, precision))); // converted units whole numbers to int 
    int fractionX = (int) (units % (Math.pow(10, precision))); // converts the decimal as an int 

    int intY = (int) (other.getUnits()/(Math.pow(10, other.getPrecision()))); // converted units whole numbers to int 
    int fractionY = (int) (other.getUnits() % (Math.pow(10, other.getPrecision()))); // converts the decimal as an int 

    System.out.println("Test: i " + intX + "| f " + fractionX + "| u " + units + "| p " + precision); 
    System.out.println("Test2: i " + intY + "| f " + fractionY + "| u " + other.getUnits() + "| p" + other 
    .getPrecision 
    ()); 

    if (intX > intY) return 1; 
    else if (intX < intY) return -1; 
    else { 
     if (fractionX > fractionY) return 1; // this is where the logic fails 
     if (fractionX < fractionY) return -1; 
     else return 0; 
    } 
} 

Вот мой тест вместе с выходом

System.out.println(MoneyFactory.fromString("0.3").compareTo(MoneyFactory.fromString("0.29"))); 

System.out.println(MoneyFactory.fromString("13").compareTo(MoneyFactory.fromString("0.31456789"))); 

System.out.println(MoneyFactory.fromString("0.2999").compareTo(MoneyFactory.fromString 
("0.3"))); 

Выходной

Test: i 0| f 3| u 3| p 1 
Test2: i 0| f 29| u 29| p2 
-1 
Test: i 13| f 0| u 13| p 0 
Test2: i 0| f 31456789| u 31456789| p8 
1 
Test: i 0| f 2999| u 2999| p 4 
Test2: i 0| f 3| u 3| p1 
1 
+0

почему бы не превратить его в строку первой – Constantin

+0

я не измерили производительность на это, но то, что я использую сейчас, очень похоже на то, что я сделал бы со строкой. Это можно увидеть в редакции вместе с объяснением того, что с ней не так. Но, короче говоря, я бы подумал, что использование String уменьшит производительность настолько маленькую, насколько удастся. Но мое приложение будет использовать эти методы с высокой пропускной способностью, поэтому важно (по крайней мере для меня) микро-оптимизировать эти методы. – Manskis

+0

Если оно представлено длинным или int **, оно не является десятичным. ** Вы имеете в виду * дробь? * Я вижу «десятичный», используемый здесь, чтобы означать все * кроме * числа в нотации base-10, что все это значит. Некоторые люди здесь используют его для десятичной точки *, а другие - дробной, а теперь и thist. Не могли бы мы приложить усилия. – EJP

ответ

1

Самым простым решением было бы преобразовать одно число к общему уровню точности, а затем сравнить цифры. Если они такие же использование `номер с большей точностью» логики (в псевдокоде):

return (number1 == number2) ? [number with bigger precision logic] : number1 - number2 

В Java коде

class Money { 
    long units; 
    int precision; 

    public Money (long un, int prec) { 
    units = un; 
    precision = prec; 
    } 

    public int compareTo(Money other) { 
     int preResult = this.precision - other.precision; 
     long first = (preResult > 0) ? ((long)(this.units/Math.pow(10, preResult))) : this.units; 
     long second = (preResult < 0) ? ((long)(other.units * Math.pow(10, preResult))) : other.units; 
     return (first == second) ? preResult : Long.compare(first, second); 
    } 

    public static void test() { 
     Money first = new Money(2345L, 4); 
     Money second = new Money(234567L, 6); 
     System.out.println(first.compareTo(second)); 
    } 

} 

EDIT: Был ошибка в коде. Изменение 1 в обоих tenary проверок 0 устраняет эту проблему

+0

С другой стороны, я не думаю, что это сработает. Если у меня есть «0.2345» и «0.234567», и я проверяю, будет ли первое больше второго, «0.234567» будет нарезано «0.2345». Если я использую 'ROUND_HALF_EVEN', это сработает, но если тестовый пример:' 0.2345' больше, чем '0.23454', он потерпит неудачу. Возможно, я что-то упустил? – Manskis

+0

Сначала вы конвертируете одно число в тот же уровень точности, что и '0.2345 == 0.2345'. Второе число «0.234567» имеет большую точность, поэтому оно больше, поэтому -1 нужно возвращать. если первое число имеет большую точность 1, нужно вернуть. В противном случае верните 'number1 - number2' – MaxZoom

+0

спасибо за помощь, которую я очень ценю. Я понимаю ваш метод намного лучше, и я думаю, что это может сработать. Я провел несколько тестов кода, который вы предоставили, и он не работает в этой строке. 'Assert.assertEquals (-1, новые деньги (152L, 2) .compareTo (Деньги (22L, 1)));' Это возвращает меня 1. Я буду продолжать работать над этим. – Manskis

0

Я думаю, вы просто сделать это следующим образом:

public int compareTo(Money other) { 

    return Double.compare(units/Math.pow(10, precision), other.getUnits()/Math.pow(10, other.getPrecision())); 
} 
Смежные вопросы