Pull to refresh

Решение проблемы сложения и вычитания чисел с плавающей точкой

Доброго времени суток. Как Говориться, краткость — сестра таланта, поэтому статья будет четкой и максимально информативной.


Введение


Когда начал изучать Python, я наткнулся на очень любопытную, раннюю неизвестную мне тему 'Как устроены вещественные числа'. В ней говорилось про мантиссу, экспоненту и прочие детали вроде отведение битов на хранение числа.



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


Суть проблемы


Из-за способа представления чисел с плавающей точкой операции с ними имеют не абсолютную точность. В этот момент меня, как новичка, просто поразило, как самая точная, совершенная машина не в состоянии посчитать точно даже банальные вещественные числа. Тем более мы все знаем, на что способны компьютеры в наше время, неужели такое может быть? Да, действительно, программа не в состоянии сложить два вещественных числа, которые без труда посчитает школьник в пятом классе:


x = 0.1
y = 0.2
print(x + y)  # 0.30000000000000004

Ну, почти точно, скажете вы. Кому важен 17 знак после запятой (P.S. иногда важен). Сейчас представьте, что вам нужно посчитать не два числа, а допустим, двадцать, и подумайте, какая погрешность будет из-за того, что она будет возрастать каждый раз в геометрической прогрессии.


Решение


Как разрешить эту проблему мне пришло в голову следующим образом: надо всего лишь заставить программу считать такие числа как человек. То есть оперировать строго целыми числами. Ведь мы делаем так же.


На бумаге идея представлялось довольно легко, осталось только реализовать практически.
При написании кода возникали ошибки различного типа, но в итоге получилось создать именно то, что и хотелось — функцию, которая будет складывать и вычитать числа как человек, то есть, опять повторюсь, оперируя только целыми числами.


Ссылка на код GitHub


Конечная функция состоит из 3 алгоритмов:


  1. Решает задачу сложения положительных вещественных чисел
  2. Решает задачу сложения отрицательных вещественных чисел
  3. Сочетает в себе два предыдущих, позволяя складывать и вычитать любые положительные и отрицательные числа с плавающей точкой.

Общий итог


Любой учитель математики скажет вам, что точность — самое главное в исчислении. По моему мнению, в программировании она не менее важна. Инженерное дело, фотонная, атомная физика, биология — всем этим областям важная самая максимальная точность, где даже незначительная погрешность приведет к неверным результатам.


Примеры исчисления


Как вводятся данные для рассчета

Функция принимает на вход строки, в которых записаны вещественные числа, на выходе тоже возращает число, представленное type: <class 'str'>


Посчитаем что-то очень большое:


print(plum('0.01230000000000081038091823910983901308129838123891182391273819381981213120043',
           '-1.0917498000000007327647819830913901312318238911238173123719237892749023421'))  
           # -1.07944979999999992238386374398155111815052550988490548845918559545509021089957
print(0.01230000000000081038091823910983901308129838123891182391273819381981213120043
           -1.0917498000000007327647819830913901312318238911238173123719237892749023421)  
           # -1.0794498

И что-нибудь поменьше:


print(plum('0.002130031201237', '-1.905771892300819', '47.088812039793'))  # 45.185170178693418
print(0.002130031201237 - 1.905771892300819 + 47.088812039793)  # 45.18517017869342

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

Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.