Проблемы с двойной точностью при увеличении

У меня есть этот алгоритм, который вычисляет значение Мандельброта точки (x0,y0) (x0 и y0 находятся где-то между -1 и 1, я думал, что не очень важно). Все идет очень хорошо, когда scale не становится слишком большим, но при более высоких значениях scaleвозвращенные значения очень неточные, и мой графический вывод начинает выглядеть странно. Как я могу предсказать, из какого значения scale это происходит?

    public static byte CalculateMandelbrot(double x0, double y0,double scale)
    {
        x0 /= scale;
        y0 /= scale;
        double y = 0;
        double x = 0;
        byte i = 0;
        while (x * x + y * y < 4)
        {
            double tx = x;
            x = x * x - y * y + x0;
            y = 2 * tx * y + y0;
            i++;
            if (i == 0xFF) break;
        }

        return i;
    }

2 ответа

Решение

Двойной имеет 53 бит точности. Это составляет около 16 знаков после запятой.

Если вы увеличите фрактал в 10^13 раз и получите изображение размером 1000x1000 пикселей, точность будет примерно равна разрешению экрана: минимальное возможное изменение в два раза - это шаг одного пикселя на экране.

Но до этого у вас будут проблемы, потому что вы повторяете итерацию формулы Мандельброта сто раз итеративно для одного и того же числа. Каждый расчет добавляет ошибку округления (несколько, вероятно) около 1/10^16. Можно (хотя и утомительно) предсказать, когда это станет заметным.

Внутренний блок FPU имеет большее число битов, чем стандартный double, это уменьшит вышеупомянутый эффект.

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

Со справочной страницы C#:

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

Существуют также реализации произвольной точности, такие как BigFloat Class.

Другие вопросы по тегам