· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.A&O —› -= Float_to_Str =- (алгоритм 5)

<< . 1 . 2 . 3 .

Посл.отвђт Сообщенiе


Дата: Май 22, 2004 20:55:56 · Поправил: Quantum

Black_mirror
Ого! Бум пробовать. Благодарю!!!

ЗЫ: Вот это Дзен!
 ||
\||/
 \/


Дата: Май 23, 2004 00:30:39 · Поправил: Black_mirror

Устранены баги с округлением:
;destroy: edx,ecx and two floating-point register
;return: eax - end of string
float_to_str:;(str +4,float +8)
	xchg edi,[esp+4]
	mov edx,[esp+8]
	shl edx,1
	fld dword [esp+8]
	mov al,'+'
	jnc .positive
	mov al,'-'
	fchs
    .positive:
	stosb
	cmp edx,0ff000000h
	mov eax,'INF'
	jz .special
	mov eax,'NAN'
	ja .special
	mov eax,4D104D43h	;lg(2)
	shr edx,24
	mul edx
	sub eax,0EE0606B8h	;126*lg(2) = 25.EE0606B9
	sbb edx,25h+1
	fmul qword [.pw2+edx*8+8]
	fcom [.f2in31]
	fnstsw ax
	sahf
	jb .noscale
	inc edx
	fmul [.f01]
    .noscale:
	fistp dword [esp+8]
	push edx
	mov edx,[esp+8]
	lea edx,[edx*4+edx]
	mov eax,edx
	and eax,0f0000000h
	sub edx,eax
	shr eax,28
	add eax,'0.'
	stosw
	mov ecx,6
    .outfraq:
	shl edx,1
	lea edx,[edx*4+edx]
	mov eax,edx
	and eax,0f0000000h
	sub edx,eax
	shr eax,28
	add al,'0'
	stosb
	loop .outfraq
	pop edx
	test edx,edx
	mov al,'+'
	jns .epositive
	mov al,'-'
	neg edx	
    .epositive:
	stosb
	xchg eax,edx
	aam 10
	xchg al,ah
	or ax,'00'
	stosw
	mov byte [edi],0
    .exit:
	mov eax,edi
	mov edi,[esp+4]
	ret 8
    .special:
        fstp st0 ;<- добавлено для исправления злого бага
	stosd
	dec edi
	jmp .exit
    .i10 dd 10
    .i31 dd 31
    .f01 dd 0.1
    .f2in31 dd 2147483648.0
;10^(-n)*2^28	n=[-38..+38]
     dd 02A16A1B1h,49A2CED3h , 04357691Ch,496E17B8h
     dd 0CF7920E3h,493812F9h , 072C74D82h,49034261h
     dd 0EAD87C04h,48CED09Bh , 02246C99Dh,4898A6E3h
     dd 0B5056E17h,4863B8B5h , 08808B024h,482F8DEFh
     dd 039A08CEAh,47F93E59h , 0FAE6D721h,47C431E0h
     dd 02F1F1281h,479027E7h , 0E4FE8402h,4759D971h
     dd 0B7320335h,4724ADF4h , 02C280291h,46F08B2Ah
     dd 079D99DB4h,46BA7843h , 0C7E14AF6h,46852D02h
     dd 0064DD592h,4650F0CFh , 0D6E2EF50h,461B1AE4h
     dd 078B58C40h,45E5AF1Dh , 060913D00h,45B158E4h
     dd 0674EC800h,457BC16Dh , 085D8A000h,45463457h
     dd 037E08000h,4511C379h , 026340000h,44DC6BF5h
     dd 01E900000h,44A6BCC4h , 0E5400000h,4472309Ch
     dd 0A2000000h,443D1A94h , 0E8000000h,44074876h
     dd 020000000h,43D2A05Fh , 000000000h,439DCD65h
     dd 000000000h,4367D784h , 000000000h,433312D0h
     dd 000000000h,42FE8480h , 000000000h,42C86A00h
     dd 000000000h,42938800h , 000000000h,425F4000h
     dd 000000000h,42290000h , 000000000h,41F40000h
.pw2 dd 000000000h,41C00000h , 09999999Ah,41899999h
     dd 047AE147Ch,41547AE1h , 0D2F1A9FDh,4120624Dh
     dd 0EB1C4330h,40EA36E2h , 088E368F4h,40B4F8B5h
     dd 0A0B5ED90h,4080C6F7h , 09ABCAF4Eh,404AD7F2h
     dd 0E2308C3Fh,4015798Eh , 0E826D699h,3FE12E0Bh
     dd 0D9D7BDC3h,3FAB7CDFh , 0E179649Ch,3F75FD7Fh
     dd 0812DEA18h,3F419799h , 06849768Dh,3F0C25C2h
     dd 086A12BA4h,3ED6849Bh , 09EE7561Eh,3EA203AFh
     dd 097D889CAh,3E6CD2B2h , 04646D4A2h,3E370EF5h
     dd 0D1D243B5h,3E02725Dh , 04FB6D2BCh,3DCD83C9h
     dd 00C924232h,3D979CA1h , 00A0E9B5Ch,3D62E3B4h
     dd 010175EF9h,3D2E3920h , 04012B262h,3CF82DB3h
     dd 099A88EB5h,3CC357C2h , 0F5DA7DEFh,3C8EF2D0h
     dd 0C4AECB27h,3C58C240h , 036F23C1Fh,3C23CE9Ah
     dd 0BE506035h,3BEFB0F6h , 0FEA6B35Eh,3BB95A5Eh
     dd 0FEEBC2B1h,3B84484Bh , 06589688Fh,3B5039D6h
     dd 0D5A8A74Ch,3B19F623h , 077BA1F70h,3AE4C4E9h
     dd 092FB4C5Bh,3AB09D87h , 0B7F87A2Bh,3A7A95A5h
     dd 0932D2E8Ah,3A454484h , 0428A8BA2h,3A11039Dh
     dd 09DAA7903h,39DB38FBh


Дата: Июн 2, 2004 23:20:17 · Поправил: Black_mirror

;переводит число расширенной точности в символьный вид
;при возврате eax указывает на байт сразу за числом
long_double_to_str:;(str +4, long double +8(12 байт))
	fnstcw [esp+18]
	push edi	;+4
	mov edi,[4+esp+4]	;указатель на стороку
	mov edx,[4+esp+16]	;порядок и знак числа
	fldcw [.cwnear]		;расширеная точность, округление к ближайшему
	fld tword [4+esp+8]	;загружаем число
	mov al,'+'
	shl edx,17		;в cf - знак числа
	jnc .positive
	mov al,'-'		;меняем знак числа
	fchs
    .positive:
	stosb			;выводим знак числа
	shr edx,17		;порядок числа
	cmp edx,7FFFh		;проверяем на особое значение
	jz .special
;вычисляем десятичный порядок
	mov eax,4D104D43h	;lg(2)
	mul edx			;p(двоичный)*lg(2)
	lea ecx,[esp] ;align
	sub eax,46405238h	;16383*lg(2)-1/2=1343.4640523781h
	sbb edx,1343h		;десятичный порядок
	lea ecx,[esp] ;align
;возведение 10  в степень -p
	mov eax,.p1-12		;таблицуа 10^(2^n)
	mov ecx,edx
	fld1
	neg ecx			;-p(десятичный)
	jz .endpw		;p=0
	jns .power      	;-p>0
	neg ecx			;меняем знак
	mov eax,.m1-12          ;таблицуа 10^-(2^n)
    .power:
	add eax,12
	shr ecx,1		;тестируем бит порядка
	ja .power
	fld tword [eax]		;умножаем на соответствующую степень 10
	fmulp
	jnz .power
    .endpw:	
	fmulp			;умножаем число на 10^-p
	fld1			;сравниваем получившееся число с 1
	fcomp st1
	fnstsw ax
	sahf
	jbe .great1		
	fmul [.ten]		;если меньше, домножаем на 10
	dec edx			;корректируем порядок
    .great1:
	fldcw [.cwdown]		;округление вниз
	fist word [edi]		;сохраняем первую цифру
	fisub word [edi]	;вычисляем остаток
	inc edi
	inc edi

;st0 - дробная часть числа, выводим с точностью 18 цифр

	push edx	;+8
	fmul qword [.c1e18]
	fistp qword [8+esp+8]
	mov eax,[8+esp+8]
	lea ecx,[esp+1234]	;align
	nop			;align
	mov edx,[8+esp+12]
	div [.i1e9]	;num=eax*1e-9+edx*1e-18
	push edx
	stc
	rcl eax,2       ;умножаем старшую часть на 2^64/1e9
	mul [.cc]	
	shrd eax,edx,31	;eax - число формата 0.32
	mov ecx,9
    .l0:		;находим старшие 9 цифр
	mul [.i10]
	mov [edi],dl
	inc edi
	loop .l0
	pop eax
	stc
	nop			;align
	rcl eax,2	;умножаем младшую часть на 2^64/1e9
	mul [.cc]
	shrd eax,edx,31
	mov ecx,9
    .l1:		;находим младшие 9 цифр
	mul [.i10]
	mov [edi],dl
	inc edi
	loop .l1
	pop edx

;старая версия цикла
;	mov ecx,18
;    .outdigit:
;	fmul [.ten]
;	fist word [edi]
;	fisub word [edi]
;	inc edi
;	loop .outdigit
;	fstp st0

;преобразуем в ASCII
	mov eax,'0000'
	add dword [edi-20],'0.00'
	add [edi-16],eax
	add [edi-12],eax
	add [edi-8],eax
	add [edi-4],eax
;выводим символ и знак порядка
	mov ax,'E+'
	test edx,edx
	jns .epositive
	mov ah,'-'
	neg edx
    .epositive:	
	stosw
;выводим порядок
	mov al,100
	xchg eax,edx
	div dl
	ror eax,8
	aam 10
	bswap eax
	aam 10
	xchg al,ah
	or eax,'0000'
	stosd

	mov byte [edi],0	;записываем завершающий нуль
	xchg eax,edi
	pop edi
	fldcw [esp+18]	
	ret 16
;обрабатываем специальные значения 
    .special:
	fstp st0
	mov eax,'NAN'
	mov edx,[4+esp+12]	;если мантиста = 80000000 00000000, то это INF
	shl edx,1		;иначе это не число
	jnc .nan
	or edx,[4+esp+8]
	jnz .nan
	mov eax,'INF'
    .nan:
	stosd
	dec edi
	xchg eax,edi
	pop edi
	fldcw [esp+18]
	ret 16

align 4
    .cc dd 2305843009 ;2^61/10^9
    .i10 dd 10
    .i1e9 dd 1000000000
    .c1e18 dq 1e18	
    .ten dd 10.0
    .cwnear dw 033Fh
    .cwdown dw 073Fh

.p1	dd $00000000,$A0000000,$4002;$00000000
.p2	dd $00000000,$C8000000,$4005;$00000000
.p4	dd $00000000,$9C400000,$400C;$00000000
.p8	dd $00000000,$BEBC2000,$4019;$00000000
.p16	dd $04000000,$8E1BC9BF,$4034;$00000000
.p32	dd $2B70B59E,$9DC5ADA8,$4069;$F0200000;^ округлено в большую сторону
.p64	dd $FFCFA6D5,$C2781F49,$40D3;$3CBF6B71;v округлено в меньшую сторону
.p128	dd $80E98CE0,$93BA47C9,$41A8;$C66F336C;^
.p256	dd $9DF9DE8E,$AA7EEBFB,$4351;$DDBB901B;^
.p512	dd $A60E91C7,$E319A0AE,$46A3;$CC655C54;^
.p1024	dd $81750C17,$C9767586,$4D48;$650D3D28;v
.p2048	dd $C53D5DE5,$9E8B3B5D,$5A92;$A74D28CE;^
.p4096	dd $8A20979B,$C4605202,$7525;$C94C153F;^
.m1	dd $CCCCCCCD,$CCCCCCCC,$3FFB;$CCCCCCCC;^
.m2	dd $70A3D70B,$A3D70A3D,$3FF8;$3D70A3D7;v^ дополнительно увеличено на 1
.m4	dd $E219652D,$D1B71758,$3FF1;$D3C36113;^^
.m8	dd $8461CEFE,$ABCC7711,$3FE4;$FDC20D2B;^^
.m16	dd $C44DE15C,$E69594BE,$3FC9;$4C2EBE68;v^
.m32	dd $453994BA,$CFB11EAD,$3F94;$67DE18ED;v
.m64	dd $A539E9A5,$A87FEA27,$3F2A;$3F2398D7;v
.m128	dd $64BCE4A1,$DDD0467C,$3E55;$AC7CB3F6;^
.m256	dd $637A193A,$C0314325,$3CAC;$FA911155;^
.m512	dd $DB23D21C,$9049EE32,$395A;$7132D332;v
.m1024	dd $DA57C0BE,$A2A682A5,$32B5;$87A60158;^
.m2048	dd $34362DE4,$CEAE534F,$256B;$492512D4;v
.m4096	dd $D2CE9FDE,$A6DD04C8,$0AD8;$2DE38123;v


На данный момент одно преобразование на атлоне выполняется за 500 тактов. Может у кого есть идеи для оптимизации по скорости и/или точности вычислений? (таблицу на 90К не предлагать)


Дата: Июн 2, 2004 23:37:34

А вот тестирующая програмка(перенаправив вывод в файл можно посмотреть на результаты преобразований).

1459977548__ld2s.zip

<< . 1 . 2 . 3 .


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.069