Pull to refresh

Перевод числа в строку с помощью FPU

Reading time 9 min
Views 6.4K

Введение

Часто требуемое для вывода результатов расчетов преобразование числа с «плавающей точкой» из формата IEEE-754 в текстовую строку в «научной» нотации (т.е. с показателем степени «E») не является совсем уж тривиальной задачей. В силу обстоятельств автору пришлось самостоятельно «изобретать велосипед» такого преобразования. Причем хотелось сделать это максимально эффективно, в полной мере используя аппаратные возможности обработки чисел.

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

Постановка задачи

Формализуем задачу. Необходимо перевести восьмибайтовое число из формата IEEE-754 в текстовую строку, где указан знак числа, мантисса заданной длины и десятичный порядок с признаком «E» и своим знаком.

Так, если задано число 1234.567890, то строка с мантиссой, например, в 16 знаков должна выглядеть как « 1.23456788999999E+003». Вместо плюса у мантиссы нужно писать пробел, а сама мантисса должна быть не меньше единицы. Кстати, данный пример иллюстрирует дискретность и приближенность представления чисел в формате IEEE-754: приведенное исходное число не может быть точно представлено как «1.23456789000000E+003», что, может быть, интуитивно ожидалось.

Использование команд FPU для преобразования

На первый взгляд, решение выглядит простым. В устройстве FPU (Floating Point Unit) процессора даже имеются команды, явно предназначенные и для перевода чисел из формата IEEE-754 в текст. Это, во-первых, команда EXTRACT разделения числа на мантиссу и порядок, а во-вторых, команда FBSTP выдающая мантиссу сразу в виде двоично-десятичного значения. Однако при ближайшем рассмотрении эти команды не дают нужного результата.

Например, если применить команду FBSTP к указанному выше числу, то получится 10 байт со значением 35 12 00 00 00 00 00 00 00 00, поскольку нецелочисленные значения сначала округляются согласно полю RC управляющего слова FPU. Это двухбитовое поле RC может принимать 4 значения, но среди них нет режима «отключить округление». Поэтому часть мантиссы просто теряется, единственное чего можно добиться режимами округления – это еще получить значение 34 12 при округлении к меньшему.

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

Итак, при использовании возможностей FPU придется решать две задачи.

Во-первых, умножением (или делением) исходного числа на десять нужно «перегнать» всю мантиссу в целочисленную часть числа, тогда команда FBSTP выдаст, наконец, в двоично-десятичном виде все цифры мантиссы.

Во-вторых, нужно определить такой десятичный порядок (опять-таки умножением или делением на десять), при котором результат попадет в диапазон между 1 и 10. Это нужно для представления числа в виде мантиссы с одной цифрой перед точкой и найденным порядком. Увы, совместить эти две задачи в едином цикле умножения/деления невозможно.

Причем есть и «подводный камень» в виде значения числа, максимально приближенного к единице, но не равного единице. Циклом деления или умножения легко можно ошибиться в показателе степени и вместо требуемого в данном случае 9.999…E-001 получить неправильное значение типа 9.999…E+000. К сожалению, при всем богатстве команд FPU обойтись без циклов деления и умножения на десять не удается.

Алгоритм преобразования

При формировании мантиссы для числа типа «double» умножение или деление на 10 продолжаются до тех пор, пока двоичный порядок числа не достигнет (или не станет больше/меньше) 53, поскольку под мантиссу выделено именно 53 двоичных разряда.

При формировании десятичного порядка для числа типа «double» умножение или деление на 10 продолжаются до тех пор, пока двоичный порядок разницы числа и 1 не достигнет (или не станет больше/меньше) -53, что означает максимальное приближение к 1. При этом необходимо еще отслеживать частный случай ближайшего к 1 значения из одних девяток, поскольку цикл умножения или деления в этом случае дает одну «лишнюю» или одну «недостающую» степень.

Пример реализации преобразования

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

Пара комментариев к тексту. Подпрограмма написана на языке ассемблера RASM, который имеет некоторые особенности.

В частности здесь используются «временные» метки в виде символа «@». Алгоритм их реализации следующий: транслятор имеет внутренний счетчик меток. Когда метка «@» встречается в команде перехода, к ней автоматически дописывается значение этого счетчика (т.е. реально создаются метки @0000, @0001 и т.д.). Когда встречается символ «@» с двоеточием, к нему также автоматически приписывается значение счетчика и после этого счетчик увеличивается на 1.

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

Кроме этого, для команд FPU в RASM не анализируется размер операнда, он имеется прямо в названиях команд в виде значений 16, 32, 64 или 80.

Но вернемся к задаче. Подпрограмме по адресу в EBX передается исходное восьмибайтовое число в формате IEEE-754 и требуемая длина текстовой строки-результата в AL.

В результате работы число записывается в стек в виде текста в «научной» нотации и в AL сохраняется длина этой строки. Другие регистры не сохраняются.

С целью разгрузить конвейеры процессора некоторые команды «рассыпаны» по тексту и не образуют непрерывных логических цепочек, что несколько затрудняет чтение текста. Но таких мест немного. Программа реентерабельна и может быть использована в параллельных вычислениях. При начале работы программы управляющее слово FPU CW=0360.

  1. Сначала в стеке выделяется место для ответа и заполняется «нулевым» шаблоном, т.е. значением « 0.000… E+000».

  2. Затем проверяется знак числа и в зависимости от него формируется мантисса умножением или делением числа на десять.

  3. Командой FBSTP мантисса переписывается в память из FPU в двоично-десятичном виде и ее часть (заданной длины) переносится в ответ.

  4. После этого исходное число опять-таки умножением или делением на десять как можно ближе «подгоняется» к 1, что позволяет вычислить требуемый десятичный порядок, который и записывается на заранее подготовленное в ответе место.

      CSEG
PUBLIC ?QFCMW:

;---- ПОДГОТОВКА МЕСТА В СТЕКЕ ----

      MOVZX     ECX,AL          ;ЗАДАННАЯ ДЛИНА СТРОКИ
      POP       EAX             ;ДОСТАЛИ АДРЕС ВОЗВРАТА
      SUB       ESP,ECX         ;ВЫДЕЛИЛИ МЕСТО В СТЕКЕ
      MOV       EDI,ESP         ;ОНО ЖЕ НАЧАЛО СТРОКИ-РЕЗУЛЬТАТА
      MOV       ESI,ESP         ;ЗАПОМНИЛИ НАЧАЛО
      PUSH      EAX             ;АДРЕС ВОЗВРАТА ВЕРНУЛИ НА МЕСТО
      PUSH      ECX             ;ЗАПОМНИЛИ ЗАДАННУЮ ДЛИНУ ОТВЕТА

;---- СНАЧАЛА ЗАПОЛНЕНИЕ СТРОКИ-РЕЗУЛЬТАТА НУЛЕВЫМ ШАБЛОНОМ ----

      MOV       EAX,'0.0 '      ;ЗНАК И ПЕРВОЕ ЧИСЛО С ТОЧКОЙ
      STOSD
      DEC       EDI             ;ОСТАВЛЯЕМ ПЕРВЫЕ ТРИ СИМВОЛА ШАБЛОНА
      SUB       CL,8            ;ВЫЧЛИ СЛУЖЕБНЫЕ ЗНАКИ И ПОРЯДОК
      MOV       AL,'0'
      JBE       @               ;ОШИБКА, НЕТ МЕСТА ПОД МАНТИССУ
      REP       STOSB           ;ЗАПОЛНИЛИ МАНТИССУ НУЛЯМИ
@:    MOV       EAX,'00+E'      ;ПОКА ДВА НУЛЯ ПОРЯДКА
      STOSD                     ;ЗАПИСАЛИ НУЛЕВОЙ ПОРЯДОК
      LEA       EBP,[EDI]-2     ;ЗАПОМНИЛИ АДРЕС ПОРЯДКА
      FLD64     [EBX]           ;ЗАГРУЗИЛИ ЗАДАННОЕ ЧИСЛО
      MOV       B PTR [EDI],'0' ;ПОКА ТРЕТИЙ НУЛЬ ПОРЯДКА

;---- ПРОВЕРКА ЗАДАННОГО ЧИСЛА НА ПЛЮС/МИНУС/НОЛЬ ----

      FTST                      ;СРАВНИЛИ С НУЛЕМ
      FNSTSW    AX
      SAHF
      JNZ       @               ;ЗАДАННОЕ ЧИСЛО НЕ НОЛЬ

;---- СРАЗУ ВЫХОД С ЧИСТЫМ НУЛЕМ ----

      POP       EAX             ;ВЫХОД С ЗАДАННОЙ ДЛИНОЙ И НУЛЕМ
      FSTP      ST              ;ОЧИСТИЛИ FPU ОТ ИСХОДНОГО ЧИСЛА
      RET

;---- ОБРАБОТКА ЗНАКА ЗАДАННОГО ЧИСЛА ----

@:    JNB       @               ;ЕСЛИ ЧИСЛО ПОЛОЖИТЕЛЬНО
      MOV       B PTR [ESI],'-' ;ОТМЕТИЛИ ЗНАК ОТРИЦАТЕЛЬНОГО
      FABS                      ;УБРАЛИ ЗНАК В САМОМ ЧИСЛЕ
@:    MOV       EDX,OFFSET ДЕСЯТЬ ;ДЕСЯТИЧНАЯ СИСТЕМА

;---- ПРОВЕРКА ВЕЛИЧИНЫ ПОРЯДКА ИСХОДНОГО ЧИСЛА ----

      FLD       ST              ;РАЗМНОЖИЛИ ПОЛОЖИТЕЛЬНОЕ ЧИСЛО
      POP       ECX             ;ОПЯТЬ ДОСТАЛИ ДЛИНУ СТРОКИ
      FXTRACT                   ;РАЗДЕЛИЛИ МАНТИССУ И ПОРЯДОК
      PUSH      ECX             ;ОПЯТЬ СОХРАНИЛИ ДЛИНУ СТРОКИ
      FSTP      ST              ;ВЫКИНУЛИ МАНТИССУ
      SUB       ESP,11          ;ВЫДЕЛИЛИ МЕСТО ПОД МАНТИССУ КАК BCD
      FIST32P   [ESP]           ;ЗАПИСАЛИ ПОРЯДОК
      CMP       D PTR [ESP],53  ;ОН УЖЕ 53 РАЗРЯДА ?
      JE        M0003           ;ТОГДА МАНТИССА УЖЕ ГОТОВА
      JL        M0002           ;ИНАЧЕ ЧИСЛО ОЧЕНЬ МАЛО

;---- УМЕНЬШЕНИЕ ПОРЯДКА ЧИСЛА ОТ ОЧЕНЬ БОЛЬШОГО ----

M0001:FLD       ST              ;РАЗМНОЖИЛИ ЧИСЛО
      FXTRACT                   ;РАЗДЕЛИЛИ МАНТИССУ И ПОРЯДОК
      FSTP      ST              ;ВЫКИНУЛИ МАНТИССУ
      FIST32P   [ESP]           ;ДОСТАЛИ ПОРЯДОК
      CMP       D PTR [ESP],53  ;УЖЕ 53 РАЗРЯДА ?
      JLE       M0003           ;ТОГДА МАНТИССА УЖЕ ГОТОВА
      FIDIV16   [EDX]           ;РАЗДЕЛИЛИ ЧИСЛО НА ДЕСЯТЬ
      JMPS      M0001           ;ПРОВЕРЯЕМ НОВЫЙ ПОРЯДОК

;---- УВЕЛИЧЕНИЕ ПОРЯДКА ЧИСЛА ОТ ОЧЕНЬ МАЛОГО ----

M0002:FLD       ST              ;РАЗМНОЖИЛИ ЧИСЛО
      FXTRACT                   ;РАЗДЕЛИЛИ МАНТИССУ И ПОРЯДОК
      FSTP      ST              ;ВЫКИНУЛИ МАНТИССУ
      FIST32P   [ESP]           ;ДОСТАЛИ ПОРЯДОК
      CMP       D PTR [ESP],53  ;УЖЕ 53 РАЗРЯДА ?
      JGE       M0003           ;ТОГДА МАНТИССА УЖЕ ГОТОВА
      FIMUL16   [EDX]           ;УМНОЖИЛИ ЧИСЛО НА 10
      JMPS      M0002           ;ПРОВЕРЯЕМ НОВЫЙ ПОРЯДОК

;---- ВЫДАЧА МАНТИССЫ В ДВОИЧНО-ДЕСЯТИЧНОМ ВИДЕ ----

M0003:FBSTP     [ESP]+1         ;ЗАПОМНИЛИ МАНТИССУ КАК BCD-ФОРМАТ

;---- ФОРМИРОВАНИЕ ТЕКСТА ИЗ BCD-МАНТИССЫ ----

      LEA       EDI,[ESI]+1     ;АДРЕС ОТВЕТА ПОСЛЕ ЗНАКА
      FLD1                      ;ЗАГРУЗИЛИ КОНСТАНТУ 1E0
      SUB       CL,7            ;ЗАДАННАЯ ДЛИНА МАНТИССЫ В ОТВЕТЕ
      FLD64     [EBX]           ;ОПЯТЬ ЗАГРУЗИЛИ ИСХОДНОЕ ЧИСЛО
      LEA       ESI,[ESP]+10    ;АДРЕС ПЕРВЫХ ЦИФР МАНТИССЫ

      STD
      MOV       DH,0            ;ПОКА НУЛИ НЕ ПИШЕМ
      FABS                      ;ЗНАК ИСХОДНОГО ЧИСЛА БОЛЬШЕ НЕ НУЖЕН
      MOV       AH,0            ;НАЧИНАЕМ С ЧЕТНОЙ ТЕТРАДЫ
      FCOM                      ;ЗАРАНЕЕ СРАВНИВАЕМ ЧИСЛО С 1E0
      MOV       BL,1            ;ПОКА ОНО МОЖЕТ БЫТЬ ВБЛИЗИ +1/-1

;---- ЦИКЛ ПЕРЕПИСИ ПО ВСЕМ ТЕТРАДАМ BCD-МАНТИССЫ ----

M0004:XOR       AH,1            ;ОЧЕРЕДНАЯ ТЕТРАДА
      JZ        @               ;ЕСЛИ НЕЧЕТНАЯ ТЕТРАДА
      LODSB                     ;ДОСТАЛИ БАЙТ МАНТИССЫ
      CMP       ESI,ESP         ;ЗА ПРЕДЕЛАМИ МАНТИССЫ ?
      MOV       DL,AL           ;ДВЕ ТЕТРАДЫ МАНТИССЫ
      JB        M0007           ;ЗАКОНЧИЛИ ВЫВОД

;---- ЧЕТНАЯ ТЕТРАДА ----

      SHR       AL,4            ;ЧЕТНАЯ ТЕТРАДА BCD
      JMPS      M0005

;---- НЕЧЕТНАЯ ТЕТРАДА ----

@:    MOV       AL,DL
      AND       AL,0FH          ;НЕЧЕТНАЯ ТЕТРАДА BCD

;---- ПРОПУСК ЛИДИРУЮЩИХ НУЛЕЙ МАНТИССЫ ----

M0005:OR        DH,AL           ;ЕЩЕ ИДУТ НУЛИ МАНТИССЫ ?
      JNZ       @               ;УЖЕ ИДУТ ЦИФРЫ МАНТИССЫ
      INC       ECX             ;НЕ УЧИТЫВАЕМ ЭТОТ НОЛЬ В МАНТИССЕ
      JMPS      M0006           ;ПРОПУСКАЕМ НЕЗНАЧАЩИЙ НОЛЬ

;---- ПРОВЕРКА НА ВСЕ ДЕВЯТКИ (Т.Е. НА ЧИСЛО ВБЛИЗИ +1/-1) ----

@:    CMP       AL,9            ;ИДУТ СПЛОШНЫЕ ДЕВЯТКИ ?
      JZ        @               ;ДА, ПРОДОЛЖАЮТСЯ ДЕВЯТКИ
      MOV       BL,0            ;УЖЕ НЕ ВБЛИЗИ +1/-1 (НЕ ДЕВЯТКА)

;---- ПРОПУСК ТОЧКИ, ЗАРАНЕЕ ЗАПИСАННОЙ В ОТВЕТ ----

@:    CMP       B PTR [EDI],'.' ;ЗДЕСЬ В ШАБЛОНЕ ТОЧКА ?
      JNZ       @
      INC       EDI             ;ПРОПУСКАЕМ ТОЧКУ

;---- ЗАПИСЬ ОЧЕРЕДНОЙ ЦИФРЫ МАНТИССЫ КАК ТЕКСТА ----

@:    ADD       [EDI],AL        ;ПИШЕМ ОЧЕРЕДНУЮ ЦИФРУ В ОТВЕТ
      INC       EDI             ;СЛЕДУЮЩИЙ АДРЕС
M0006:LOOP     M0004            ;ЗА СЛЕДУЮЩЕЙ ТЕТРАДОЙ

M0007:CLD

;---- ФОРМИРОВАНИЕ ВЕЛИЧИНЫ ПОРЯДКА ----

      MOV       ESI,OFFSET ДЕСЯТЬ
      FNSTSW    AX
      XOR       EDX,EDX         ;ПОКА ПОРЯДОК НОЛЬ
      SAHF
      JZ        M0011           ;ЧИСЛО СТРОГО РАВНО 1 - ПОРЯДОК НОЛЬ
      JA        M0009           ;ЧИСЛО БОЛЬШЕ 1 - ПОРЯДОК ПОЛОЖИТЕЛЕН
      MOV       B PTR [EBP]-1,'-' ;ОТМЕТИЛИ ОТРИЦАТЕЛЬНЫЙ ПОРЯДОК

;---- УВЕЛИЧЕНИЕ ПОРЯДКА ДО ЧИСЛА БОЛЬШЕ 1 ----

M0008:FIMUL16   [ESI]           ;УВЕЛИЧИЛИ ЧИСЛО В 10 РАЗ
      INC       EDX             ;УВЕЛИЧИЛИ ПОРЯДОК

      FCOM                      ;СРАВНИВАЕМ С 1
      FNSTSW    AX              ;ЗАПОМНИЛИ РЕЗУЛЬТАТ СРАВНЕНИЯ
      SAHF
      JZ        M0011           ;СТРОГО РАВНО 1 - НАШЛИ ПОРЯДОК

      FLD       ST              ;РАЗМНОЖИЛИ ЧИСЛО
      FSUB      ST,ST2          ;РАЗНИЦА С 1
      FXTRACT                   ;ДОСТАЛИ МАНТИССУ И ПОРЯДОК
      FSTP      ST              ;ВЫБРОСИЛИ МАНТИССУ
      FIST32P   [ESP]           ;ПОРЯДОК РАЗНИЦЫ
      CMP       D PTR [ESP],-53 ;УЖЕ ВПЛОТНУЮ К 1 ?
      JLE       M0010           ;ДА, ВПЛОТНУЮ, БЛИЖЕ НЕ БУДЕТ

      SAHF                      ;ОПЯТЬ ДОСТАЛИ ФЛАГИ СРАВНЕНИЯ С 1
      JA        M0011           ;УЖЕ БОЛЬШЕ - НАШЛИ ПОРЯДОК
      JMPS      M0008           ;ПРОДОЛЖАЕМ УМНОЖАТЬ НА 10

;---- УМЕНЬШЕНИЕ ПОРЯДКА ДО ЧИСЛА МЕНЬШЕ 1 ----

M0009:FIDIV16   [ESI]           ;УМЕНЬШИЛИ ЧИСЛО В 10 РАЗ
      INC       EDX             ;УМЕНЬШИЛИ ПОРЯДОК

      FCOM                      ;СРАВНИВАЕМ С 1
      FNSTSW    AX              ;ЗАПОМНИЛИ РЕЗУЛЬТАТ СРАВНЕНИЯ
      SAHF
      JZ        M0011           ;СТРОГО РАВНО 1 - НАШЛИ ПОРЯДОК

      FLD       ST              ;РАЗМНОЖИЛИ ЧИСЛО
      FSUB      ST,ST2          ;РАЗНИЦА С 1
      FXTRACT                   ;ДОСТАЛИ МАНТИССУ И ПОРЯДОК
      FSTP      ST              ;ВЫБРОСИЛИ МАНТИССУ
      FIST32P   [ESP]           ;ПОРЯДОК РАЗНИЦЫ
      CMP       D PTR [ESP],-53 ;УЖЕ ВПЛОТНУЮ К 1 ?
      JG        @               ;ЕЩЕ НЕ ВПЛОТНУЮ
M0010:INC       EBX             ;ПРИЗНАК НАХОЖДЕНИЯ ВБЛИЗИ 1
      JMPS      M0011           ;ПЕРЕСТАЕМ ИСКАТЬ ПОРЯДОК

@:    SAHF                      ;ОПЯТЬ ЗАГРУЗИЛИ ФЛАГИ СРАВНЕНИЯ С 1
      JNB       M0009           ;ПРОДОЛЖАЕМ ДЕЛИТЬ НА 10
      DEC       EDX             ;ЧИСЛО В ОТВЕТЕ ДОЛЖНО БЫТЬ БОЛЬШЕ 1

M0011:ADD       ESP,11          ;ОСВОБОДИЛИ СТЕК ОТ BCD-МАНТИССЫ

;---- КОРРЕКТИРОВКА ПОРЯДКА ВБЛИЗИ +/-1 ----

      CMP       BL,2            ;БЫЛИ ВСЕ ДЕВЯТКИ И ПОЧТИ 1 ?
      XCHG      EAX,EDX         ;ДОСТАЛИ ЗНАЧЕНИЕ ПОРЯДКА
      JNZ       @               ;НЕТ, ЧИСЛО НЕ ВБЛИЗИ 1
      DEC       EAX             ;ВБЛИЗИ 1 СВЕРХУ, ДЕЛАЕМ 0.999...E+000
      CMP       B PTR [EBP]-1,'-' ;ЧИСЛО МЕНЬШЕ 1E0 ?
      JNZ       @               ;НЕТ, БОЛЬШЕ
      INC       EAX             ;ВЕРНУЛИ ПОРЯДОК
      INC       EAX             ;ВБЛИЗИ 1 СНИЗУ,  ДЕЛАЕМ 9.999...E-001

;---- ЗАПИСЬ СТАРШЕЙ ЦИФРЫ ПОРЯДКА ----

@:    PUSH      100
      XOR       EDX,EDX
      POP       EBX             ;ДЕЛИМ НА КОНСТАНТУ 100
      FSTP      ST              ;ОЧИЩАЕМ FPU ОТ ПОИСКА ПОРЯДКА
      DIV       EBX             ;ПОЛУЧАЕМ ЧАСТНОЕ - ПЕРВУЮ ЦИФРУ
      ADD       [EBP],AL        ;СТАРШАЯ ЦИФРА ПОРЯДКА

;---- ЗАПИСЬ ДВУХ МЛАДШИХ ЦИФР ПОРЯДКА ----

      MOV       BL,10           ;ДЕЛИМ НА КОНСТАНТУ 10
      XCHG      EAX,EDX         ;ОСТАТОК ОТ ДЕЛЕНИЯ НА 100
      DIV       BL              ;ЧАСТНОЕ И ОСТАТОК - ДВЕ ЦИФРЫ ПОРЯДКА
      FSTP      ST              ;ВЫБРОСИЛИ КОНСТАНТУ 1 ИЗ FPU
      ADD       [EBP]+1,AX      ;ДВЕ ОСТАЛЬНЫЕ ЦИФРЫ ПОРЯДКА

;---- ВЫХОД С ОТВЕТОМ В СТЕКЕ И ДЛИНОЙ СТРОКИ В AL ----

      POP       EAX             ;ДЛИНА СТРОКИ ОТВЕТА В СТЕКЕ
      RET

      DSEG
ДЕСЯТЬ DW 10                    ;БАЗА ДЛЯ ПЕРЕВОДА В ДЕСЯТИЧНУЮ СИСТЕМУ

Заключение

Использование команд FPU сделало данную реализацию довольно компактной (326 байт команд) и удовлетворительной по скорости. Например, на компьютере с процессором Intel Core Solo 1.33 GHz сто миллионов преобразований числа 1234.567890 в текст заняли 89 секунд.

Таким образом, скорость работы данной подпрограммы составила 845 преобразований в секунду на каждый мегагерц тактовой частоты процессора. При этом полный отказ от использования команд FPU вряд ли позволит увеличить скорость требуемого преобразования.

Однако эффективность преобразования числа в текст могла бы быть повышена, если бы разработчики FPU предусмотрели режим «без округления» для команды FBSTP. Это позволило бы при применении этой команды для перевода мантиссы в текст избежать циклов умножения и деления на десять лишь только для получения всех значащих цифр.

Tags:
Hubs:
+16
Comments 23
Comments Comments 23

Articles