Ошибки с плавающей запятой

У меня проблемы с плавающей запятой. А двойник. 56 в Java, например, может фактически храниться как .56000...1.

Я пытаюсь преобразовать десятичную дробь в дробь. Я пытался сделать это, используя непрерывные дроби

Непрерывные дроби

но мои ответы с использованием этого метода были неточными из-за того, как компьютер хранил и округлял десятичные числа.

Я попробовал альтернативный метод:

public static Rational rationalize(double a){
        if(a>= 1){
        //throw some exception
    }
    String copOut = Double.toString(a);

    int counter = 0;
    System.out.println(a);
    while(a%1 != 0 && counter < copOut.length() - 2){
        a *= 10;
        counter++;
    }
    long deno = (long)Math.pow(10,counter);//sets the denominator
    Rational frac = new Rational((long)a,deno)//the unsimplified rational number
    long gcd = frac.gcd();
    long fnum = frac.getNumer();//gets the numerator 
    long fden = frac.getDenom();//gets the denominator
    frac = new Rational(fnum/gcd, fden/gcd);
    return frac;    
}

Я использую строку, чтобы найти длину десятичного числа, чтобы определить, сколько раз я должен умножить на 10. Позже я усекаю десятичное число. Это дает мне правильный ответ, но это не похоже на правильный подход? Может ли кто-нибудь предложить «правильный» способ сделать это?


person Zhv Z    schedule 18.02.2014    source источник
comment
Первая проблема здесь заключается в том, что input равен double.. Таким образом, вы уже теряете точность еще до того, как ваш код будет выполнен. Подумайте о BigDecimal.   -  person user207421    schedule 18.02.2014


Ответы (1)


На самом деле у вас все отлично. Но это не удастся, если на входе будет что-то вроде 11.56. Здесь вам нужно сделать copOut.length() - 3.

Чтобы сделать его динамичным, используйте String#split()

String decLength = copOut.split("\\.")[1]; //this will result "56" (Actual string after decimal)

Теперь вам просто нужно сделать только

while(a%1 != 0 && counter < decLength.length()){
        a *= 10;
        counter++;
    }

Если вы хотите удалить цикл, используйте

long d = (long)Math.pow(10,decLength.length());
 a=a*d;
person AJ.    schedule 18.02.2014