Найти в Дзене

Повышение точности расчетов на компьютере

Повышение точности расчетов на компьютере – задача и простая, и сложная одновременно. В любом учебнике по программированию вы найдете слова «Для повышения точности используйте переменные типа DOUBLE вместо SINGLE». Других форматов такие языки, как BASIC, просто не поддерживают. В C# и в PASCAL есть формат DECIMAL или аналогичный ему, но все, кто им пользовался жалуются на многократное замедление работы программ. В то же время сопроцессор практически любого современного компьютера поддерживает еще один формат – расширенный с плавающей запятой. На всякий случай оговорюсь, что в MMX и XMM технологиях этот формат, по моим сведениям, не поддерживается.

Что же это за формат? Обозначают его по-разному. В ассемблере MASM32/64 это TBYTE, отладчик x64dbg.exe распознает его как TWORD, наверное, есть еще варианты. Буква Т впереди наименования присутствует оттого, что каждая переменная занимает в памяти 10 байт (ten). Содержит он мантиссу 64 бит (8 байт), порядок 15 бит и бит знака числа. Таким образом мантисса расширенного формата на 11 бит длиннее DOUBLE, а это число 2048, то есть три дополнительных полноценных десятичных разряда. Сам сопроцессор и его стек работают именно в этом формате. В качестве характеристики представленного формата надо сказать, что знаменитый EXCEL весь работает именно в этом формате, хотя его встроенный BASIC не дает возможности использовать TBYTE в программировании. В других языках я не встречал описания переменных, похожих на TBYTE.

К сожалению для работы с этим форматом разработчики INTEL предусмотрели только 4 ассемблерных команды:

FLD tbyte - загрузка переменной из памяти в стек;

FSTP tbyte - вывод значения из вершины стека в переменную

FSAVE - сохранения всего содержимого сопроцессора

FRSTOR - восстановление содержимого сопроцессора

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

Мне известен только один способ использования расширенного формата чисел с плавающей точкой – писать программы или отдельные библиотеки динамической загрузки на языке Ассемблер. Я работаю на нем почти сорок лет, пишу сложные и простые программы, диалоги и непрерывные технологические циклы, работы с различными протоколами передачи данных и хранения сведений (не базы типа SQL, конечно, но заказчик доволен).

Приветствую всех, кто заинтересуется Ассемблером и постараюсь ответить на Ваши вопросы.