· Начало · Статистика · WASM.RU · Noir.Ru ·

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

<< . 1 . 2 .

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


Дата: Сен 17, 2003 16:26:47

Black_mirror
Если процедура _exp10 использует функцию fx2m1

Там всё ОК.


Дата: Сен 17, 2003 16:49:16

Black_mirror
Спасибо!!!
Но это всё ещё нужно будет менять :))В самом старшем бите находится знак числа, а не экспоненты!

можно заменить на jle @F
Упппсс :)))
Умница!!!!

Можно обойтись без умножения 96и-битного числа:
Если привести мантисту к диапазону [1..10) то сдвигать ее придется не в право, а в лево. После первого сдвига мы получим целую часть в самом старшем слове и дробную в оставшихся 64х битах. Умножая в цикле дробную часть на 10 мы получим оставшиеся цифры.


Меня сейчас волнует немного другое ..
ТОЧНОСТЬ.

А как быть с периодическими дробями? Думаешь цифры закончатся после умножения на 2^64 ?

Нет, не закончатся. Но и не должны они закончится.

Но выводит больше 20 цифр смысла все равно нет. У меня даже 20я цифра мусор. Нужно придумать как это правильно округлить.

А вот в этом ГОСПОДА и вся загвостка..
Но я могу утверждать, что этот алгоритм имеет единственный шанс на абсолютную точность результата...
Ибо в нём не теряются биты...
(Почти)


Дата: Сен 17, 2003 17:16:16

Смутно припоминаю один из университетских курсов про представление данных в вычислительных машинах... там кажется говорилось что не все 10чные дроби могут быть представлены конечной двоичной и наоборот.... вот вам и проблемы округления :)


Дата: Сен 17, 2003 17:55:30

Смутно припоминаю один из университетских курсов про представление данных в вычислительных машинах... там кажется говорилось что не все 10чные дроби могут быть представлены конечной двоичной и наоборот.... вот вам и проблемы округления :)

Объясняю тонкость бытия.

Нужно создать таки две функции Str_to_Float/Float_to_Str
Чтобы они давали одинаковый результат.


Дата: Сен 17, 2003 18:02:34

Edmond
а если подсмотреть в msvcrt?? :)


Дата: Сен 17, 2003 18:10:37

DaemoniacaL
Ааа, давайте.
Только плиз ИСХОДНИКИ В СТУДИЮ!!!
(Пусть дизассемблированные)


Дата: Сен 17, 2003 19:38:25

Edmond
Нужно создать таки две функции Str_to_Float/Float_to_Str
Чтобы они давали одинаковый результат


Можно любое двоичное число абсолютно точно перевести в десятичное представление. Но не всякое десятичное число можно преобразовать в двоичное. Проблемма в том, что 1/5 можно представить только ввиде двоичной периодической дроби, а при возведении ее в степень, длина периода только увеличивается, и может составлять величину порядка (1/5)^n цифр, где n - количество цифр после точки в исходном числе.

По поводу точности:
Точность long double 64 бита, эти 64 бита мы только умножаем на 10, поэтому никаких битов мы не потеряем если правильно выполним округление. Основные потери происходят при возведении 10 в степень и делении или умножении на нее исходного числа.

Алгоритм который выполнет преобразование long double в строку абсолютно точно, должем перевести его в формат с фиксированной точкой в котором 16 тысяч бит до запятой и столько же после, а затем последовательными делениями целой части на 10 найдет цифры целой части, и последовательными умножениями дробной части на 10 найдет все цифры дробной части.


Дата: Сен 17, 2003 22:39:13 · Поправил: Fixer

По поводу точности

Вроде это где-то обсуждалось здесь.

DaemoniacaL

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


Дата: Сен 19, 2003 14:30:15

Fixer
Вроде это где-то обсуждалось здесь.

И не доопсуждалось :)))
ОК, после выходных я выпущу бету :))


Дата: Сен 20, 2003 09:58:31

;абсолютно точное преобразование long_double в строку 
long_double_to_str:;(str +4, long_double +8, unused_word +18)
;размер строки должен быть 1+1+1+16383+63+1 байт
;результат:
;в str - символьное представление числа
;eax указывает на (последний записанный символ+1)
	push ebp
	push esi
	push edi	;+12
	mov edi,[12+esp+4]
;выделяем память, чтобы преобразовать lond_double в fixed_point_16416.16448
	mov ecx,4108/4
    .alloc:
	push 0		;+4120
	loop .alloc
	mov edx,[4120+esp+8+8]	;exponent
	test dx,dx
	jns .no_sign
	mov al,'-'
	stosb
    .no_sign:
;вычисляем на сколько нужно сдвинуть мантисту и куда ее записать
	and edx,7fffh	
	lea ecx,[edx+2]
	add edx,2
	and ecx,31
	and edx,-32
	shr edx,3
;сдвиг и запись
	xor eax,eax
	mov ebx,[4120+esp+8+4]
	shld eax,ebx,cl
	mov [esp+edx+8],eax
	mov eax,[4120+esp+8]
	shld ebx,eax,cl
	mov [esp+edx+4],ebx
	shl eax,cl
	mov [esp+edx],eax
	lea ebp,[esp+2056]
;преобразование целой части
	mov esi,2052
	xor eax,eax
	push -'0'
    .l0:	;отбрасывание ведущих нулей
	sub esi,4
	js .out_zero
    .l1:	
	xor eax,eax
	cmp dword [ebp+esi],eax
	jz .l0
	mov ecx,esi
	xor edx,edx
    .l2:	;делим целую часть на 10
	mov eax,[ebp+ecx]
	div [.c10]
	mov [ebp+ecx],eax
	sub ecx,4
	jns .l2
	push edx	;сохраняем цифру
	or eax,esi	
	jnz .l1		;если целая часть не ноль, то делим снова
    .l4:	;вывод цифр
	pop eax
    .out_zero:
	add al,'0'
	stosb
	jnz .l4
	dec edi
    .out_pt:
	mov al,'.'
	stosb
;преобразование дробной части
	mov esi,-2060
    .l6:	;отбрасывание завершающих нулей
 	add esi,4
	jns .exit
    .l8:
	cmp dword [ebp+esi],0
	jz .l6
	xor ebx,ebx
	mov ecx,esi
    .l7:	;умножаем дробную часть на 10
	mov eax,[ebp+ecx]
	mul [.c10]
	add eax,ebx
	adc edx,0
	mov [ebp+ecx],eax
	mov ebx,edx
	add ecx,4
	js .l7
	or eax,esi
	lea eax,[edx+'0']	;выводим цифру
	stosb
	jnz .l8		;если дробная часть не ноль, то умножаем снова
    .exit:
	cmp al,'.'
	jnz .l9
	dec edi
    .l9:
	mov byte [edi],0
	add esp,4108	;+12
	xchg eax,edi
	pop edi
	pop esi
	pop ebp		;+0
	ret 16
    .c10 dd 10


Дата: Сен 20, 2003 12:03:16

;абсолютно точное преобразование long_double в строку

Это как? :))))))
Абсолютно точное не бывает :))


Дата: Сен 20, 2003 22:45:33

Edmond
Преобразовать число с плавающей точкой в число с фиксированной точкой без потерь можно. Затем можно преобразовать целую часть в строку. Далее если мы будем умножать дробную часть на 10 то в конце концов дробная часть обнулится, так как один из множителей десяти двойка, а умножение на 2 в двоичной системе эквивалентно сдвигу на разряд в сторону точки с заполнением младшего разряда нулем. По моему преобразование выполняется абсолютно точно.


Дата: Сен 22, 2003 10:43:12

Black_mirror
Преобразовать число с плавающей точкой в число с фиксированной точкой без потерь можно.

Логично.

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

ОК. Проверим.

<< . 1 . 2 .


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