Как я уже отмечал в предыдущем посте, с помощью Julia невероятно легко выполнять высокоточные арифметические операции.



Хотя это правда, что с Джулией это легко сделать, все же есть некоторые вещи, с которыми вам нужно быть осторожным, чтобы убедиться, что вы получаете ожидаемые результаты. Чтобы продемонстрировать это, я запущу Джулию и запущу несколько примеров.

julia> x = BigFloat(1.0)
1.0

Здесь нет ничего удивительного. Я сказал ему создать переменную x, используя тип BigFloat, и он распечатал результат 1.0. Теперь создадим значение BigFloat для деления 1 на 7.

julia> y = BigFloat(1.0/7.0)
0.142857142857142849212692681248881854116916656494140625

На первый взгляд мы видим много цифр после запятой, поэтому похоже, что мы получили нужное значение BigFloat. Десятичное представление 1/7 — это повторяющееся десятичное число с использованием цифр 142857, которое продолжается вечно, например: 1/7 = 0,142857142857142857142857…. Но посмотрите внимательно на результат, который дала нам Джулия, и хотя он начинается достаточно хорошо, он довольно быстро перестает повторяться. Что пошло не так?

Ответ заключается в том, что Джулия преобразовала выражение «1.0/7.0» выше в Float64, его тип с плавающей запятой по умолчанию, и только затем это значение было передано для преобразования в BigFloat. Другими словами, он преобразовал 1,0/7,0 в значение двойной точности (Float64) и округлил его до значения двойной точности, а затем взял это округленное значение и преобразовал его в BigFloat. Хотя y имеет тип BigFloat, он начинается только с точностью Float64.

На самом деле, если вы преобразуете любое постоянное число в BigFloat таким образом, у вас вполне могут возникнуть проблемы. Например, давайте попробуем получить значение BigFloat для 0,2:

julia> y2 = BigFloat(0.2)
0.200000000000000011102230246251565404236316680908203125

Как видите, мы уже теряем точность всего на 17 знаков после запятой. Один из способов исправить это — указать исходную константу в виде строки, чтобы Джулия должна была преобразовать ее непосредственно в BigFloat:

julia> y2 = BigFloat("0.2")
0.2000000000000000000000000000000000000000000000000000000000000000000000000000004

Вот чего мы хотим! Эта проблема также возникает при манипуляциях с константами. Например, предположим, что мы хотели добавить 0,2 к нашему значению x выше:

julia> y3 = x + 0.2
1.200000000000000011102230246251565404236316680908203125

Как видите, это тоже не сработало. Хотя это правда, что Джулия преобразует свой общий результат в BigFloat, сначала она видит 0,2 как значение Float64. Затем он преобразует 0,2 с двойной точностью в BigFloat и добавляет его к x, поэтому в конечном результате мы потеряли точность. Было бы очень легко иметь подобную ошибку в вашем коде, и в большинстве случаев вы, вероятно, даже не знали бы, что она есть.

Итак, возвращаясь к нашему самому первому примеру, мы установили x как BigFloat 1.0, и это, по-видимому, сработало отлично. Почему этот код работал, а более поздние примеры — нет? В этом примере нам просто повезло, так как мы выбрали целое число, которое было округлено правильно. В тот раз это сработало, но в целом на это рассчитывать не приходится.

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