-1

Имеется рекурсивный код для вычисления цепной дроби:

import java.math.*;
import java.io.*;
import java.util.*;

public class ContinuedFraction {
    public static void main(String args[ ]) {
        double z= cep(1071/462);
        System.out.println(z);
    }

    public static double cep(double drobchast)
    {
        if((1/drobchast) - (Math.ceil(1/drobchast) - 1) == 0) {
            return 1/drobchast;
        }
        double celchast = Math.ceil(1/drobchast) - 1;
        drobchast = 1/(celchast + (1/drobchast));
        return cep(drobchast);
    }
}

Попробую объяснить свою логику: условие
(1/drobchast) - (Math.ceil(1/drobchast) - 1) == 0 предполагает, что если перевернуть дробь и у нее не останется остатка (например, перевернём 1/7 и получим 7), значит дошли до конечной точки.

Иначе нужно передать единицу, деленную на отрезанную от дроби целую часть, плюс единицу, деленную на перевернутую дробь.

Сейчас при запуске моего кода выводится ошибка стека.

Andrey
  • 80
  • Для большей понятности вы можете внести свой комментарий в вопрос, а также подробнее описать возникшую проблему. Иначе этот вопрос могут закрыть из-за плохого качества. – Timofei Bondarev Apr 30 '15 at 23:14
  • у меня выходит ошибка стека – Andrey Apr 30 '15 at 23:16
  • Старайтесь аккуратно оформлять вопросы. На будущее: справку по редактированию вопросов можно найти здесь – Timofei Bondarev Apr 30 '15 at 23:25
  • все было нормально написано, зачем исправлять все!!! – Andrey Apr 30 '15 at 23:32
  • В состоянии, в котором был вопрос до изменения, его бы с большой вероятностью заминусовали и закрыли. – Timofei Bondarev Apr 30 '15 at 23:40
  • Есть ещё одна небольшая ошибка: cep(1071/462) эквивалентно cep(2), так как и делимое, и делитель являются целыми числами.
    По возможности дополните также ожидаемым результатом для вашей программы и способом его вычисления.
    – Timofei Bondarev May 01 '15 at 00:27

1 Answers1

2

Функция cep завершится с крайне малой вероятностью, проще сказать, что она никогда не завершится и уйдёт в бесконечную рекурсию.

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

Обычно для сравнения с нулём заводят число, меньше которого все дробные числа считаются нулём, например,

EPSILON = 1e-6
if (Math.abs(value) < EPSILON) { // считаем здесь, что value == 0 }

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


Способом более точно работать с дробями будет также создание класса, отдельно хранящего числитель и знаменатель как целые числа. В таком случае не возникнет потери точности при многочисленных операциях с дробью.

На основном сайте есть обсуждение реализации подобного класса

  • это я понял и так, что с нулем не пройдет этот фокус, а как теперь все исправить? – Andrey Apr 30 '15 at 23:35
  • Можно либо ввести EPSILON, либо воспользоваться второй частью моего ответа. Быть может, кто-то предложит более подходящий способ – Timofei Bondarev Apr 30 '15 at 23:39
  • ясно что ни чего не ясно... и на этом спасибо – Andrey Apr 30 '15 at 23:44