Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Алгоритмы > Помогите преобразовать float в строку


Автор: SOIC 23.4.2003, 21:29
Необходимо реализовать функцию преобразования float в строку, т.к.
стандартные функции C (sprintf, ecvt) сильно кушают стек (до 200 элементов)
а у меня всего 128 элементов стека под всю задачу...

Нужен алгоритм преобразования float в строку...

Автор: neutrino 23.4.2003, 21:38
Приветствую!
Ну смотри... Формат таков:
[31] бит - знак (s)
[30-24] - степень (p)
[23-0] - мантисса (m)

А дальше...

A=(-1)^s*2^(p-127)*m

вот и все...

Автор: stab 11.6.2003, 11:02
Цитата
А дальше...

A=(-1)^s*2^(p-127)*m

вот и все...


хм, а собственно что делать дальше ?

Автор: Chingachguk 11.6.2003, 12:57
Из моей статьи (http://www.wasm.ru/print.php?article=approx):

Цитата

; ***** ValToString: Подпрограмма форматирования числа типа Real в строку ******
; [ebp+8] - Адрес строки(будет Zero-terminated) в виде 12345.89
; [ebp+0Сh] - Адрес числа типа real (или dd)
; [ebp+10h] - Маска вывода числа (byte)
ValToString proc
.code
  push ebp
  mov  ebp,esp
  ; Локальные переменные:
  ; [ebp-4] - модуль числа
  ; [ebp-08] - максимальная степень 10-ти в числе
  ; [ebp-0Ch] - временная
  sub  esp,4*3
  cld
  mov  edi,dword ptr [ebp+8]            ; Адрес выходной строки
  mov  ebx,[ebp+0Ch]                    ; Загружаем адрес числа в ebx
  mov  edx,[ebx]                        ; Читаем его в edx
  ; Определяем знак, удаляя его одновременно (31 бит)
  shl  edx,1
  jnc  @@NoSign
  mov  al,'-'
  stosb
@@NoSign:
  shr  edx,1
  mov  [ebp-4],edx                      ; Запоминаем модуль числа в локальной переменной
  ; Проверка на ноль
  test edx,edx
  jnz  @@NonZero
  mov  al,'0'
  stosb
  jmp  @@DoneValToStr
@@NonZero:
  ; Определяем старшую степень десяти - Log10(x) = Log2(x)/Log2(10)
  ; Выполняется в два приема, поскольку нет операции Log10 в FPU, а есть y*Log2(x)
  ; Получаем 1/Log2(10)
  fld1                                  ; Загрузить 1.0
  fldl2t                                ; Загрузить log2(10)
  fdivp ST(1),ST(0)                    ; Разделить 1/log2(10), результат в ST(0)
  fld  dword ptr [ebp-4]                ; Загрузить наше число, 1/log2(10) протолкнуть в ST(1)
  fyl2x ; ST(0)=ST(1)*log2(ST(0))
  ; Задаем режим округления (биты 11 - отбросить дробную часть)
  call Set_FPUTruncType
  frndint
  fistp dword ptr [ebp-8]              ; Выгрузить степень как целое со знаком
  ; Задаем режим округления (биты 00 - округлить до ближайшего целого)
  call Set_FPURoundType
  ; Сохранить степень числа
  push dword ptr [ebp-8]
  ; Вывести число, деля его на 10^...
  ; Вывести целую часть числа, точку, дробную часть
  mov  ecx,dword ptr [ebp+10h]          ; Сколько цифр после десятичной точки выводить
  inc  ecx                              ; Цифра перед десятичной точкой
  xor  edx,edx                          ; Флаг вывода точки
@@OutNumbers: 
  fld  dword ptr DecNumber              ; Загрузить 10 - основание
  mov  eax,dword ptr [ebp-8]            ; Степень
  call get_pow                          ; ST(0) = 10^Степень
  fld  dword ptr [ebp-4]                ; Загрузить число
  ; ST(0)=Число, ST(1) = 10^Степень
  fdiv ST(0),ST(1)                      ; ST(0)=ST(0)/ST(1)
  ; Задаем режим округления (биты 11 - отбросить дробную часть)
  call Set_FPUTruncType
  frndint
  fistp dword ptr [ebp-0Ch]            ; Выгружаем как целое без округления
  ; Задаем режим округления (биты 00 - округлить до ближайшего целого)
  call Set_FPURoundType
  ; Выводим цифру
  mov  eax,dword ptr [ebp-0Ch]
  mov  ebx,1
  call DecChar                          ; В формате - @n1
  inc  edi
  ; Выводим точку, если это необходимо
  test edx,edx
  jnz  @@PointAlreadyOut
  mov  al,'.'
  stosb
  inc  edx
@@PointAlreadyOut:
  ; Вычесть из числа 10^Степень(сейчас в ST(0)) x Текущая цифра
  fimul dword ptr [ebp-0Ch]
  fld  dword ptr [ebp-4]                ; Загрузить число
  fsub ST(0),ST(1)
  fstp dword ptr [ebp-4]                ; Выгрузить число с вычетом
  fstp ST(0)                            ; Очистить стек
  ; Уменьшить степень на 1
  dec  dword ptr [ebp-8]
  loop @@OutNumbers
  ; Восстановить степень числа
  pop  dword ptr [ebp-8]
  ; Вывести степень 10-ти
  mov  ax,'+E'
  mov  edx,[ebp-8]
  cmp  edx,0
  jge  @@NoNegPower
  neg  edx
  mov  ah,'-'
@@NoNegPower:
  stosw 
  mov  eax,edx
  mov  ebx,1000
  call DecChar                          ; В формате @n4
  add  edi,4     
@@DoneValToStr: 
  mov  byte ptr [edi],0
  leave
  ret  3*4
ValToString endp

Автор: stab 11.6.2003, 22:00
млин, лучше б в CPU вшили инструкции atoi, itoa, ftoa, atof smile.gif

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)