Введение в арифметику с плавающей точкой

Рассмотрим, как выполняются команды над вещественными числами на простых примерах. До сих пор мы работали только с целыми числами, и вся арифметика подчинялась правилам обычной арифметики, за одним исключением: эти правила переставали соблюдаться, когда мы выходили за границы разрядной сетки. Т.е. из-за того, что процессор работает с ограниченным числом битов, мы не могли представить в нем число, которое было бы больше максимального числа, или меньше минимального. Внутри этого диапазона правила машинной арифметики совпадали с правилами обычной арифметики. С вещественными числами все обстоит иначе: там правила обычной арифметики не действуют. Для вещественных чисел, как мы помним, если взять любые два вещественных числа на числовой прямой, то между ними найдется бесконечно много других вещественных чисел. В процессоре, из-за того, что у него ограниченное число битов разрядной сетки, он не может представить все эти числа. Например, если взять формат float, то между 1 и 2 можно представить всего таких чисел, но если взять интервал не от 1 до 2, а от 1 до 1000000, то между двумя целыми числами будет примерно 8 вещественных чисел. Значит все остальные числа приходится округлять к одному из этих чисел.

Рассмотрим простой формат вещественных чисел. Один разряд отводится под целую часть, отведем два разряда под дробную часть, называемую мантиссой, затем в нашем формате будет экспонента, то есть 10 в какой-то степени, под нее мы тоже отведем два разряда. Например, возьмем число 12.3 . В экспоненциальном формате оно запишется как 12.3e0, то же самое можно записать как 1.23e1 . Чтобы получить из первого формата второй, мы поделили число на 10, таким образом передвинули точку влево на один знак, и одновременно инкрементировали показатель экспоненты.

Теперь сложим два числа в таком формате – 1.23е1 и 4.56е0. Для этого надо сначала выровнять экспоненту. Первое число не изменяем, а во втором переносим запятую влево, получаем 0.456e1, затем сложим с первым числом, получим 1.686е1, но если мы посмотрим на наш формат, то получим 1.69е1 , так как нужно его округлить до двух разрядов после запятой. Можно сделать вывод – для повышения точности вычислений, необходимы дополнительные цифры при вычислениях. Иначе результат будет менее точным. Таким образом в вещественных числах необходимы дополнительные биты во время вычислений. Это так называемые gvard bits. Они не доступны программисту, и используются для более точных вычислений и последующего округления.

Рассмотрим следующий пример сложим 1.23е3 и 1. Приводим экспоненты к одинаковому значению, получаем: 1.23е3 и 0.001е3. Складываем эти два числа, получаем 1.23е3. То есть из-за того, что у нас в формате предусмотрено только два разряда под дробную часть, то прибавление такого маленького числа не изменило исходное число.

Теперь сделаем такую операцию: сложим опять 1.23е3 с 1 десять раз. Складываем, но получается опять то же самое число. Теперь давайте поменяем порядок вычислений – сначала сложим десять раз 1, получим 10 или 0.01е3. А затем сложим результат с нашим числом, и получим 1.24е3. То есть можем сделать вывод, что ошибка при вычислениях накапливается, и порядок вычислений может повлиять на результат. Значит нужно стараться складывать и вычитать величины близкие друг к другу.

Следующий пример покажет, что при сложении или вычитании можно получить ложную точность, то есть точность, которая не будет достигнута. Вычтем из числа 1.23е0 число 1.22е0. Результат будет 0.01е0, преобразуем его в более удобной форму, делая так, чтобы целая часть была не нулевая, то есть получаем 1е-2, и видим только одну значащую цифру, а цифры после запятой не относятся к нашему результату. Многие процессоры в таких ситуациях в эти последние значащие разряды вставляют случайные цифры. Вывод из этого примера такой: при вычитании двух чисел с одинаковыми знаками или сложении двух чисел

Ссылка на основную публикацию
Adblock detector
x