Эффективный алгоритм для рационализации поплавков

Учитывая число с плавающей запятой, я хочу получить String представление рационального числа, приближающегося к десятичному (в пределах заданного допуска ε в порядке). Мой текущий подход заключается в следующем:

String rationalize(double d)
{
    String s = Double.toString(d);
    s = s.substring(s.indexOf('.')+1, s.length());
    return s + " / " + ApintMath.pow(new Apint(10), s.length()).toString();
}

Если вы не знакомы с ним, ApintMath.pow будет работать даже с произвольно длинными числами, и это хорошо, потому что я пытаюсь преобразовать десятичные числа с тысячами знаков после запятой. Производительность моего алгоритма ужасна.

Я связываю это с двумя вещами, но их может быть больше:

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

Как бы вы это сделали? Есть ли другие области, о которых я не говорил, которые замедляют меня?


person Andy Shulman    schedule 02.04.2012    source источник
comment
stackoverflow.com/ вопросы/474535/   -  person assylias    schedule 02.04.2012
comment
Также связано: числа с плавающей запятой"> stackoverflow.com/questions/7563669/   -  person Mysticial    schedule 03.04.2012


Ответы (1)


Здесь показана реализация дерева Стерна-Брокота здесь, но вам придется пройти профиль, чтобы увидеть, что лучше.

Приложение: я получил хорошие результаты, используя org.jscience.mathematics.number.Rational в линейных системах. ; org.apache.commons.math.fraction.BigFraction предлагает несколько конструкторов для double это может быть полезно. Все выдают подходящие исключения для неопределенных значений.

person trashgod    schedule 02.04.2012
comment
К сожалению, библиотека, которую я использую для рациональных чисел, выдает исключение при попытке построить 1/0. - person Andy Shulman; 02.04.2012
comment
Я не знаком с этой библиотекой, но похоже, что это правильно. Я привел несколько вариантов выше. - person trashgod; 03.04.2012
comment
Обошел проблему - использовал дерево Штерна-Броко, но сузил область, потому что знал, что у меня не будет рациональных значений выше или ниже определенных значений. Спасибо за предложение. - person Andy Shulman; 03.04.2012
comment
Хорошая идея. Присмотревшись, я вижу, что этот Rational игнорирует нулевой знаменатель , используя Rational(1/0) как положительную бесконечность. - person trashgod; 03.04.2012
comment
Примечание для всех, кто читает это: дерево Штерна-Броко не быстрее, чем алгоритм, который я опубликовал выше, поскольку они дают ответ медленнее. Однако они генерируют дроби меньшего размера и намного быстрее для выполнения вычислений, по крайней мере, для моего приложения. - person Andy Shulman; 03.04.2012