powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / странности конвертации float в varchar
27 сообщений из 27, показаны все 2 страниц
странности конвертации float в varchar
    #36351777
SQLMantis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
Adaptive Server Enterprise/ 12 . 5 . 4 /EBF  14065  ESD# 3 

create table aaa (bbb float)
go

insert into aaa (bbb) values ( 0 . 133 )
go

select bbb from aaa
go

 0 . 133 

select convert(varchar,bbb) from aaa
go

. 13300000000000001 

select convert(varchar,bbb+ 1 ) from aaa
go

 0 . 133 

select convert(varchar,bbb+ 10 ) from aaa
go

 10 . 132999999999999 
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36351830
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQLMantis пишет:

А в чём суть странности ? Я никакой странности вообще не вижу.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36351862
SQLMantis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv,
можно просветить меня?
Я тоже не хочу видеть этой странности или не хочу считать ее за странность :)
Столкнулся с необходимостью конкатинации поля float в строку.
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36351955
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQLMantis пишет:

> можно просветить меня?
> Я тоже не хочу видеть этой странности или не хочу считать ее за
> странность :)

Ну, закрой глаза, и повторяй: "Я не вижу никакой странности ...
Я не вижу никакой странности ..."

Но чтобы окончательно излечить тебя, доктор должен
знать точно, в чём именно заключается болезнь.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36351961
Фотография komrad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQLMantisMasterZiv,
можно просветить меня?
Я тоже не хочу видеть этой странности или не хочу считать ее за странность :)
Столкнулся с необходимостью конкатинации поля float в строку.

SQLMantis,
наверно не конкатенации, а конвертации?

float - неточный тип данных (Approximate numeric datatype).
тынц

у тебя не ошибка тут?


авторselect convert(varchar,bbb+1) from aaa
go

0 .133
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36352030
SQLMantis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv
SQLMantis пишет:

> можно просветить меня?
> Я тоже не хочу видеть этой странности или не хочу считать ее за
> странность :)

Ну, закрой глаза, и повторяй: "Я не вижу никакой странности ...
Я не вижу никакой странности ..."

Но чтобы окончательно излечить тебя, доктор должен
знать точно, в чём именно заключается болезнь.


Болезнь, видимо, заключается в непонимании каким образом ASE хранит float.
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36352062
SQLMantis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
komradSQLMantisMasterZiv,
можно просветить меня?
Я тоже не хочу видеть этой странности или не хочу считать ее за странность :)
Столкнулся с необходимостью конкатинации поля float в строку.

SQLMantis,
наверно не конкатенации, а конвертации?

float - неточный тип данных (Approximate numeric datatype).
тынц

у тебя не ошибка тут?


авторselect convert(varchar,bbb+1) from aaa
go

0 .133

Мне нужно конвертить float в varchar именно при конкатинации полей таблицы в строку.
Самое паршивое, мне надо матчить эти строки с подобными из другой таблицы.
Получая, при конвертации, единицу в конце строки сматчить ничего не получается.
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36352176
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQLMantis пишет:

> Болезнь, видимо, заключается в непонимании каким образом ASE хранит float.

Хранит он их как массив из байтов, как и все остальные типы данных.
Ничего особенного.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36352205
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQLMantis пишет:

> Мне нужно конвертить float в varchar именно при конкатинации полей
> таблицы в строку.
> Самое паршивое, мне надо матчить эти строки с подобными из другой таблицы.
> Получая, при конвертации, единицу в конце строки сматчить ничего не
> получается.

Ты, видимо, используешь не тот тип данных. Видимо, тебе нужен бы был
numeric.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36352356
Фотография komrad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQLMantis
Мне нужно конвертить float в varchar именно при конкатинации полей таблицы в строку.
Самое паршивое, мне надо матчить эти строки с подобными из другой таблицы.
Получая, при конвертации, единицу в конце строки сматчить ничего не получается.
конкатенация - это сложение, складывание ( тынц )
то что делаешь ты - конвертация в другой тип данных

float - не точный тип данных
для сравнения/матчинга конверти его например в Money, либо numeric
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36352660
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
komrad wrote:

> float - не точный тип данных
> для сравнения/матчинга конверти его например в Money, либо numeric

А смысл ? Сравнивать-то ты будешь не оригинальный float, а уже его
округлённое представление. Хотя в сравнении (на равенство) float-ов
тоже мало смысла.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36353405
iLLer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
select bbb from aaa
go

 0 . 133 

select convert(varchar,bbb) from aaa
go

. 13300000000000001 
В этом я тоже вижу странность. Почему без конвертации результат 0.133, а с конвертацией не такой? Я бы понял, если с конвертацией и без нее выдавалось .13300000000000001, однако ж тут пишут об обратном. Это не совсем правильно и очевидно.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
select convert(varchar,bbb+ 1 ) from aaa
go

 1 . 133 

select convert(varchar,bbb+ 10 ) from aaa
go

 10 . 132999999999999 

А здесь действительно ничего удивительного. После операции сложения, число меняет свое представление из-за разрядности сетки хранения.
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36353512
Фотография Ggg_old
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
два значения типа float можно считать равными если разница между ними меньше определенной малой величины. Значение этой величины вы должны определеить для себя сами исходя из необходимой точности вычислений в вашей задаче. А сравнивать числа с плавающей точкой но основании их текстового представления - классика индусского кода.
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36353518
Фотография komrad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iLLer
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
select bbb from aaa
go

 0 . 133 

select convert(varchar,bbb) from aaa
go

. 13300000000000001 
В этом я тоже вижу странность. Почему без конвертации результат 0.133, а с конвертацией не такой? Я бы понял, если с конвертацией и без нее выдавалось .13300000000000001, однако ж тут пишут об обратном. Это не совсем правильно и очевидно.


а это что вернет?

Код: plaintext
1.
2.
declare @m money
select @m= 20 . 3894 
select @m, convert(varchar( 20 ),@m)
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36353604
iLLer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
komrad,

А чтобы не вернуло, видимый результат должен быть одинаковым. Глядя в монитор мы же видим не числа, а их СТРОКОВОЕ представление. ISQL прежде чем выдать инфу переводит ее в читаемый вид с его точки зрения (а вернее программиста его писавшего). Когда же просят сделать конвертацию на стороне сервера, он почему-то делает это "тупо", тоже видимо, по мнению уже другого программиста его писавшего.

В том и дело, что клиент и сервер имеют разные понятия о переводе объекта типа А в объект типа Б. И дело не в том, плавающая тут точка или нет. Это тоже самое, если бы положительные числа сервер конвертил добавляя спереди знак плюс, а клиент при выводе положительных чисел спереди писал знак подчеркивание. Ну было бы логично ожидать, что клиент и сервер, созданные одной конторой придерживались одних принципов при конвертации. Однако это не обязательно.
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36354549
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iLLer wrote:
> select bbb from aaa
> go
>
> *0*.*133*
>
> select convert(varchar,bbb) from aaa
> go
>
> .*13300000000000001*
>
> В этом я тоже вижу странность. Почему без конвертации результат 0.133, а
> с конвертацией не такой?

Одно преобразуется на сервере, в одной архитектуре, а
другое -- на клиенте, возможно, в другой архитектуре.
Учитывая то, что float-ы в принципе равны могут быть очень
приблизительно, не понятно, в чём странность.

Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36354557
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
komrad wrote:

> declare @m money
> select @m=20.3894

Кстати, угадайте, какой ТИП ДАННЫХ имеет константа справа от
присваивания ? Просто не все знают ...

Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36354690
SQLMantis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv,

Код: plaintext
1.
2.
3.
4.
select  20 . 3894 + 'aaa'
go 

Implicit conversion from datatype 'VARCHAR' to 'NUMERIC' is not allowed

NUMERIC ?
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36354704
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQLMantis wrote:

> NUMERIC ?

Молодец, возьми с полки пирожок !
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36361760
iLLer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv
Одно преобразуется на сервере, в одной архитектуре, а
другое -- на клиенте, возможно, в другой архитектуре.
Учитывая то, что float-ы в принципе равны могут быть очень
приблизительно, не понятно, в чём странность.

Я дико извиняюсь за настырность, но все же.
А что один рубль в юниксах - это не тоже самое что один рубль в виндах? Или 0.25 вещественное число не одно и тоже на разных полушариях? Или еще как-то? Не нужно путать сравнение чисел и сравнение иных типов данных, преобразованных из чисел с плавающей запятой.

Повторюсь еще раз, для неопытных читателей, которые на основании всего треда могут сделать неверный вывод "float отстой, нигде его не применять".
Само по себе значение какого-либо типа одинаково везде и всегда, это аксиома. Не нужно путать уровень представления, с уровнем данных. Вот когда говорят, что сравнивать два числа с плавающей запятой нельзя, нужно читать такие утверждения с осторожностью. Ибо все можно сравнивать, и оно будет равняться, если это одно и тоже. Мне не хочется вдаваться в суть чисел с плавающей запятой, т.к. суть странности заключалась не в них. Но если настаиваете, то можно и на их примере. Вот представим, что мы машина, нам дают на вход 80 бит числа с плавающей запятой (1010001010001110101...0101). Есть только определенные правила, которые указывают какой бит за что отвечает и все. Нам дали указание выдать это число на свет божий, чтобы оператор ЭВМ увидел его. Вот скажите мне, имеет ли право влиять на видимый результат: расположение компа в космосе, установленная операционная система, архитектура процессора, объем свободной памяти, настройки шрифта, места преобразования (кухня, спальня, серверная, Кремль)? Ответ: нет, нет и нет. Ничто не имеет право влиять. 80 бит числа с плавающей запятой должны однозначно преобразовываться в строковое представление (и я скажу, оно-таки преобразуется, можно попрактиковаться на бумажке). А вот тут уже самое интересное. При сравнении двух видимых результатов, видно, что либо какой-то алгоритм излишне навязывает несуществующие данные (занимается припиской), либо какой-то алгоритм недостаточно точно занимается преобразованием и отбрасывает значащие цифры (занимается творчеством). Речь идет исключительно о преобразовании одного и того же числа, а не результата математических операций.
На АСА
Код: plaintext
select convert(float, 0 . 133 ),convert(char,convert(float, 0 . 133 ))
отрабатывает более чем логично, при том, что клиент 32 разрядная винда, а сервер 64 разрядный линукс. В обоих случаях выдает .133000001311302. В случае АСЕ имеет место быть произвол клиента (это был ISQL?), который решил показать вещественное число, переданное с сервера, в урезанном виде. Может там есть настройки, говорящие урезать отображение таких чисел до 8 знаков после запятой? Мне это не известно. Если их там нет, то смело можно писать гневное письмо в Sybase, почему вещественное число отображается с плохой точностью, т.е. фактически искажается. Это тоже самое, что если б в базе хранили "table", а при преобразованиях на сервере получалось "стол", а на клиенте "стол, вроде бы".
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36362389
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iLLer wrote:

> Я дико извиняюсь за настырность, но все же.
> А что один рубль в юниксах - это не тоже самое что один рубль в виндах?
> Или 0.25 вещественное число не одно и тоже на разных полушариях? Или еще
> как-то? Не нужно путать сравнение чисел и сравнение иных типов данных,
> преобразованных из чисел с плавающей запятой.

Я тоже дико извиняюсь, если ты хранишь свои рубли во float/double --
то вполне может быть и так.

> треда могут сделать неверный вывод "float отстой, нигде его не применять".

Почему же нигде ? при статистических вычислениях, при физических
вычислениях, при хранении и обсчёте результатов измерений каких-то величин,
и т.п.

> Само по себе значение какого-либо типа одинаково везде и всегда, это
> аксиома.

Ну, касательно float/double -- там есть некий стандарт, но в принципе
никто не запрещает конкретному процессору ему не следовать.

> нужно читать такие утверждения с осторожностью. Ибо все можно
> сравнивать, и оно будет равняться, если это одно и тоже.

Понятие "одно и то же" для float/double чаще всего трактуют
как "почти одно и то же", "приблизительно равно".

> скажите мне, имеет ли право влиять на видимый результат: расположение
> компа в космосе, установленная операционная система, архитектура
> процессора, объем свободной памяти, настройки шрифта, места
> преобразования (кухня, спальня, серверная, Кремль)? Ответ: нет, нет и
> нет.

Да, да, да. Нет, конечно такие уже совсем не относящиеся вещи влиять
не могут, но архитектура процессора -- почему же нет ?

Ничто не имеет право влиять. 80 бит числа с плавающей запятой
> должны однозначно преобразовываться в строковое представление (и я
> скажу, оно-таки преобразуется, можно попрактиковаться на бумажке). А вот

Самое главное, что "строковое представление" -- это конечная десятичная
дробь. А в ЭВМ число представляется как конечная двоичная дробь.
Не каждая конечная десятичная дробь может быть представлена как конечная
двоичная дробь и наоборот. И не каждое число может быть представлено
как конечная дробь вообще. Так что об однозначном преобразовании не
может быть речи, т.е. оно конечно может быть однозначным, если доопределить
правила округления при преобразованиях.

> творчеством). Речь идет исключительно о преобразовании одного и того же
> числа, а не результата математических операций.

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

> чисел до 8 знаков после запятой? Мне это не известно. Если их там нет,
> то смело можно писать гневное письмо в Sybase, почему вещественное число
> отображается с плохой точностью, т.е. фактически искажается. Это тоже

Ну, пиши, посмотрим, что тебе скажут на это ...

Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36362420
SQLMantis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iLLer, тут дело вовсе не в клиенте.
Заранее прошу прощения за "простыню", которую тут вывешиваю, но в таком виде, если дискуссия продолжится, общаться будет удобнее.
И так. Я решил спуститься сразу на нижний уровень и посмотреть как ASE будет хранить мой float.

1) Создаем тестовую таблицу.
Код: plaintext
1.
2.
create table test (a float)
go

2) Узнаем ее местоположение. Нам нужен номер страницы на которую будут попадать тестовые данные.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
dbcc tablealloc(test)
go

The default report option of OPTIMIZED is used for this run.                                                 	
The default fix option of FIX   is used for this run.                                                        	
***************************************************************                                              	
TABLE: test		OBJID =  1296004617                                                                               	
INDID= 0 	 FIRST= 721 	 ROOT= 721 	 SORT= 0                                                                          	
	Data level:  0 .   1  Data pages allocated and  1  Extents allocated.                                             	
TOTAL # of extents =  1                                                                                        	
Alloc page  512  (# of extent= 1  used pages= 2  ref pages= 2 )                                                      	
Total (# of extent= 1  used pages= 2  ref pages= 2 ) in this database                                              	
DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role.


3) Первая page имеет номер 721. На нее мы и будем смотреть.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
dbcc traceon( 3604 )
go
dbcc page(mantis,  721 ,  2 )
go

WHOLE PAGE:                                                                        	
10017c24000 (      0 ):  000002d1  00000000   00000000  4d3f7609  ............M?v.       	
10017c24010 (     16 ):  0007d302  00000000  0000002c 0881000e  ...........,....       	
10017c24020 (     32 ):   02000201   00000000  0fd20000  00000006   ................       	
10017c24030 (     48 ):   00000200   00020006   00000000   00000000   ................       	
10017c24040 (     64 ):   00000000   00000000   00000000   00000000   ................       	
10017c24050 (     80 ):   00000000   00000000   00000000   00000000   ................       	
10017c24060 (     96 ):   00000000   00000000   00000000   00000000   ................       	
10017c24070 (    112 ):   00000000   00000000   00000000   00000000   ................       	
10017c24080 (    128 ):   00000000   00000000   00000000   00000000   ................       	
10017c24090 (    144 ):   00000000   00000000   00000000   00000000   ................       	

4) Перед нами страница совершенно чистой таблицы. Внесем в нее несколько строк с одинаковым значением (0.133) и посмотрим как она изменится.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
insert into test (a) values ( 0 . 133 )
go

dbcc traceon( 3604 )
go
dbcc page(mantis,  721 ,  2 )
go

WHOLE PAGE:                                                                        	
10017c24000 (      0 ):  000002d1  00000000   00000000  4d3f7609  ............M?v.       	
10017c24010 (     16 ):  0007d318  00010000  0000003a 0881000e  ...........:....       	
10017c24020 (     32 ):   02000201   00000000  0fc20000  00000004   ................       	
10017c24030 (     48 ):  00003fc1 0624dd2f 1aa00000  00000000   ..?..$./........       	
10017c24040 (     64 ):   00000000   00000000   00000000   00000000   ................       	
10017c24050 (     80 ):   00000000   00000000   00000000   00000000   ................       	
10017c24060 (     96 ):   00000000   00000000   00000000   00000000   ................       	
10017c24070 (    112 ):   00000000   00000000   00000000   00000000   ................       	
10017c24080 (    128 ):   00000000   00000000   00000000   00000000   ................       	
10017c24090 (    144 ):   00000000   00000000   00000000   00000000   ................       	

insert into test (a) values ( 0 . 133 )
go

dbcc traceon( 3604 )
go
dbcc page(mantis,  721 ,  2 )
go

WHOLE PAGE:                                                                        	
10017c24000 (      0 ):  000002d1  00000000   00000000  4d3f7609  ............M?v.       	
10017c24010 (     16 ):  0007d31c  00020000   00000048  0881000e  ...........H....       	
10017c24020 (     32 ):   02000201   00000000  0fb20000  00000004   ................       	
10017c24030 (     48 ):  00003fc1 0624dd2f 1aa00001  00040000   ..?..$./........       	
10017c24040 (     64 ):  3fc10624 dd2f1aa0  00000000   00000000   ?..$./..........       	
10017c24050 (     80 ):   00000000   00000000   00000000   00000000   ................       	
10017c24060 (     96 ):   00000000   00000000   00000000   00000000   ................       	
10017c24070 (    112 ):   00000000   00000000   00000000   00000000   ................       	
10017c24080 (    128 ):   00000000   00000000   00000000   00000000   ................       	
10017c24090 (    144 ):   00000000   00000000   00000000   00000000   ................      

insert into test (a) values ( 0 . 133 )
go

dbcc traceon( 3604 )
go
dbcc page(mantis,  721 ,  2 )
go

WHOLE PAGE:                                                                        	
10017c24000 (      0 ):  000002d1  00000000   00000000  4d3f7609  ............M?v.       	
10017c24010 (     16 ):  0007d320  00030000   00000056  0881000e  ... .......V....       	
10017c24020 (     32 ):   02000201   00000000  0fa20000  00000004   ................       	
10017c24030 (     48 ):  00003fc1 0624dd2f 1aa00001  00040000   ..?..$./........       	
10017c24040 (     64 ):  3fc10624 dd2f1aa0  00020004  00003fc1  ?..$./........?.       	
10017c24050 (     80 ):  0624dd2f 1aa00000  00000000   00000000   .$./............       	
10017c24060 (     96 ):   00000000   00000000   00000000   00000000   ................       	
10017c24070 (    112 ):   00000000   00000000   00000000   00000000   ................       	
10017c24080 (    128 ):   00000000   00000000   00000000   00000000   ................       	
10017c24090 (    144 ):   00000000   00000000   00000000   00000000   ................       	 	

insert into test (a) values ( 0 . 133 )
go

dbcc traceon( 3604 )
go
dbcc page(mantis,  721 ,  2 )
go

WHOLE PAGE:                                                                        	
10017c24000 (      0 ):  000002d1  00000000   00000000  4d3f7609  ............M?v.       	
10017c24010 (     16 ):  0007d324  00040000   00000064  0881000e  ...$.......d....       	
10017c24020 (     32 ):   02000201   00000000  0f920000  00000004   ................       	
10017c24030 (     48 ):  00003fc1 0624dd2f 1aa00001  00040000   ..?..$./........       	
10017c24040 (     64 ):  3fc10624 dd2f1aa0  00020004  00003fc1  ?..$./........?.       	
10017c24050 (     80 ):  0624dd2f 1aa00003  00040000  3fc10624  .$./........?..$       	
10017c24060 (     96 ):  dd2f1aa0  00000000   00000000   00000000   ./..............       	
10017c24070 (    112 ):   00000000   00000000   00000000   00000000   ................       	
10017c24080 (    128 ):   00000000   00000000   00000000   00000000   ................       	
10017c24090 (    144 ):   00000000   00000000   00000000   00000000   ................       	

Я специально делал dbcc page после каждого insert'а, что бы можно было наглядно увидеть
наше float значение 0.133 в том виде в каком dbcc page его показывает.
Можно видеть что всякий раз 0.133 представлена в виде 001000400003fc10624dd2f1aa00, например или после последнего insert 003000400003fc10624dd2f1aa00

5) Теперь добавим в таблицу не 0.133 но 0.13300000000000001 и посмотрим что получилось.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
insert into test (a) values ( 0 . 13300000000000001 )
go

dbcc traceon( 3604 )
go
dbcc page(mantis,  721 ,  2 )
go

WHOLE PAGE:                                                                        	
10017c24000 (      0 ):  000002d1  00000000   00000000  4d3f7609  ............M?v.       	
10017c24010 (     16 ):  0007d328  00050000   00000072  0881000e  ...(.......r....       	
10017c24020 (     32 ):   02000201   00000000  0f820000  00000004   ................       	
10017c24030 (     48 ):  00003fc1 0624dd2f 1aa00001  00040000   ..?..$./........       	
10017c24040 (     64 ):  3fc10624 dd2f1aa0  00020004  00003fc1  ?..$./........?.       	
10017c24050 (     80 ):  0624dd2f 1aa00003  00040000  3fc10624  .$./........?..$       	
10017c24060 (     96 ):  dd2f1aa0  00040004  00003fc1 0624dd2f  ./........?..$./       	
10017c24070 (    112 ):  1aa00000  00000000   00000000   00000000   ................       	
10017c24080 (    128 ):   00000000   00000000   00000000   00000000   ................       	
10017c24090 (    144 ):   00000000   00000000   00000000   00000000   ................       	

Опять наше 0.133 или, уже даже не знаю чему верить, 0.13300000000000001. Одно ясно. Сервер хранит эти два, с нашей точки зрения ,числа одинаково.

6) Хорошо. Теперь давайте пойдем дальше.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
insert into test (a) values ( 0 . 13300000000000002 )
go

dbcc traceon( 3604 )
go
dbcc page(mantis,  721 ,  2 )
go

WHOLE PAGE:                                                                        	
10017c24000 (      0 ):  000002d1  00000000   00000000  4d3f7609  ............M?v.       	
10017c24010 (     16 ):  0007d32d  00060000   00000080  0881000e  ...-............       	
10017c24020 (     32 ):   02000201   00000000  0f720000  00000004   .........r......       	
10017c24030 (     48 ):  00003fc1 0624dd2f 1aa00001  00040000   ..?..$./........       	
10017c24040 (     64 ):  3fc10624 dd2f1aa0  00020004  00003fc1  ?..$./........?.       	
10017c24050 (     80 ):  0624dd2f 1aa00003  00040000  3fc10624  .$./........?..$       	
10017c24060 (     96 ):  dd2f1aa0  00040004  00003fc1 0624dd2f  ./........?..$./       	
10017c24070 (    112 ):  1aa00005  00040000  3fc10624 dd2f1aa0  ........?..$./..       	
10017c24080 (    128 ):   00000000   00000000   00000000   00000000   ................       	
10017c24090 (    144 ):   00000000   00000000   00000000   00000000   ................ 


Видите пятую нашу строку со смещением 10017c24070?
Получается, что 0.133==0.13300000000000001==0.13300000000000002


7) Однако, с 0.13300000000000003 дела обстоят уже не так.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
insert into test (a) values ( 0 . 13300000000000003 )
go

dbcc traceon( 3604 )
go
dbcc page(mantis,  721 ,  2 )
go

WHOLE PAGE:                                                                        	
10017c24000 (      0 ):  000002d1  00000000   00000000  4d3f7609  ............M?v.       	
10017c24010 (     16 ):  0007d331  00070000  0000008e 0881000e  ... 1 ............       	
10017c24020 (     32 ):   02000201   00000000  0f620000  00000004   .........b......       	
10017c24030 (     48 ):  00003fc1 0624dd2f 1aa00001  00040000   ..?..$./........       	
10017c24040 (     64 ):  3fc10624 dd2f1aa0  00020004  00003fc1  ?..$./........?.       	
10017c24050 (     80 ):  0624dd2f 1aa00003  00040000  3fc10624  .$./........?..$       	
10017c24060 (     96 ):  dd2f1aa0  00040004  00003fc1 0624dd2f  ./........?..$./       	
10017c24070 (    112 ):  1aa00005  00040000  3fc10624 dd2f1aa0  ........?..$./..       	
10017c24080 (    128 ):   00060004  00003fc1 0624dd2f 1aa10000  ......?..$./....       	
10017c24090 (    144 ):   00000000   00000000   00000000   00000000   ................       	

Картина стала отличаться. 00600040 0003fc10 624dd2f1 aa10
0.133==0.13300000000000001==0.13300000000000002 но не равно 0.13300000000000003

8) Виноват ли интерфейс? Нет!
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
create table test_text (a varchar( 20 ))
go

insert into test_text (a) values ('0.133')
go

select convert(varchar,convert(float,a)) from test_text
go

. 13300000000000001 

insert into test (a)   select convert(float,a) from test_text
go

WHOLE PAGE:                                                                        	
10017c24000 (      0 ):  000002d1  00000000   00000000  4d3f7609  ............M?v.       	
10017c24010 (     16 ):  0007d36d 000a0000 000000b8 0881000e  ...m............       	
10017c24020 (     32 ):   02010201   00000000  0f320000  00000000   ......... 2 ......       	
10017c24030 (     48 ):  00003fc1 0624dd2f 1aa00001  00000000   ..?..$./........       	
10017c24040 (     64 ):  3fc10624 dd2f1aa0  00020000  00003fc1  ?..$./........?.       	
10017c24050 (     80 ):  0624dd2f 1aa00003  00000000  3fc10624  .$./........?..$       	
10017c24060 (     96 ):  dd2f1aa0  00040000  00003fc1 0624dd2f  ./........?..$./       	
10017c24070 (    112 ):  1aa00005  00000000  3fc10624 dd2f1aa0  ........?..$./..       	
10017c24080 (    128 ):   00060000  00003fc1 0624dd2f 1aa10007  ......?..$./....       	
10017c24090 (    144 ):   00000000  3fc10624 dd2f1aa1  00080000   ....?..$./......       	
10017c240a0 (    160 ):  00003fc1 0624dd2f 1aa20009  00000000   ..?..$./........       	
10017c240b0 (    176 ):  3fc10624 dd2f1aa0  00000000   00000000   ?..$./..........       	
10017c240c0 (    192 ):   00000000   00000000   00000000   00000000   ................       	
10017c240d0 (    208 ):   00000000   00000000   00000000   00000000   ................	

Как видно опять храниться нечто равное 0.1330000000000000[1-2].


9) Как же сервер будет вести себя при сравнении этих величин?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
create table test_compare (a float, b float)
go

insert into test_compare (a,b) values ( 0 . 133 , 0 . 13300000000000001 )
go

select convert(varchar,a), convert(varchar,b) from test_compare where a=b
go

. 13300000000000001 	. 13300000000000001 	

insert into test_compare (a,b) values ( 0 . 133 , 0 . 13300000000000002 )
go

select convert(varchar,a), convert(varchar,b) from test_compare where a=b
go

. 13300000000000001 	. 13300000000000001 	
. 13300000000000001 	. 13300000000000001 	

insert into test_compare (a,b) values ( 0 . 133 , 0 . 13300000000000003 )
go

select convert(varchar,a), convert(varchar,b) from test_compare where a=b
go

. 13300000000000001 	. 13300000000000001 	
. 13300000000000001 	. 13300000000000001 	


select convert(varchar,a), convert(varchar,b) from test_compare where a!=b
go

. 13300000000000001 	. 13300000000000003 



В заключении выдержка из мануала.

При печати и отображении чисел с плавающей запятой то, что отобража-
ется, не полностью совпадает с тем, что хранится в памяти, как и храни-
мое в памяти число не совпадает с числом, введенным пользователем.
В большинстве случаев хранимое представление числа достаточно близ-
ко к исходному значению, и программное обеспечение выводит число,
совпадающее с введенным значением, но если числа с плавающей запя-
той используются для расчетов, особенно при выполнении многократных
расчетов с данными в приближенном представлении, то необходимо учи-
тывать погрешность, так, результаты могут быть неожиданно неточными.
Неточность возникает из-за того, что числа с плавающей запятой хранят-
ся как бинарные дроби (то есть используемые для репрезентации вещест-
венных целые числа, деленные на степень двойки), а числа, с которыми
работают пользователи, – десятичные (степени 10). Это означает, что
только очень небольшой набор чисел можно хранить полностью точно.
0,75 (3/4) может храниться точно, так как является бинарной дробью
(4 является степенью 2); 0,2 (2/10) – не может (10 не является степенью 2).
Некоторые числа содержат слишком много цифр, чтобы можно было
хранить их точно. Тип double precision хранится как 8 бинарных байтов
и может представлять около 17 цифр с удовлетворительной точностью.
Тип real хранится как 4 бинарных байта и может представлять около
6 цифр с удовлетворительной точностью.
Если на начальных этапах вычислений используются практически точ-
ные значения и затем в процесс вовлекаются другие практически точные
значения, полученный результат может сильно отличаться от точного.
Если эти аспекты важны для приложения, то необходимо использовать
типы с точным представлением чисел.
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36362511
Alexzzy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Числа с плавающей запятой http://ru.wikipedia.org/wiki/Float
Тут вроде нормально описано.

Краткая рекомендация. Если вы не уверены что вам нужен ИМЕННО float (и прочие числа с плавающей точкой) - используйте numeric.:)
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36362903
iLLer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv

Самое главное, что "строковое представление" -- это конечная десятичная
дробь. А в ЭВМ число представляется как конечная двоичная дробь.
Не каждая конечная десятичная дробь может быть представлена как конечная
двоичная дробь и наоборот. И не каждое число может быть представлено
как конечная дробь вообще. Так что об однозначном преобразовании не
может быть речи, т.е. оно конечно может быть однозначным, если доопределить
правила округления при преобразованиях.

> творчеством). Речь идет исключительно о преобразовании одного и того же
> числа, а не результата математических операций.

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


Судя по всему, никто не понял о чем я говорил. Я не говорил, про возникающее искажение информации при переводе числа из того, что мы хотим сохранить, в то, что на самом деле сохраняет машина. Я не говорил, про дискретность возникающую из-за разрядной сетки и ограниченную способность ЭВМ хранить вещественные числа. Я говорил про прямое преобразование из того, что машина уже имеет в памяти, в то, что мы видим. И не просто так привел пример с 80 битами числа с плавающей запятой. И что это прямое преобразование имеет строгий алгоритм, который НЕ МОЖЕТ ЗАВИСИТЬ (и не зависит) от архитектуры и прочего. ДА, машина не может хранить 0.133, а может хранить только ближайшее по значению число. Так вот я о том и говорю, что вот это ближайшее число и должно отображаться так, как оно есть действительно в машине. А не так, что в БД хранится .13300000000000001, а ISQL выводит .133. Еще раз повторю, в АСА такого поведения нет. Тест для проверки на нормальность:
Код: plaintext
select convert(float, 0 . 133 ),convert(char,convert(float, 0 . 133 ))
Первое значение заставит сервер вернуть клиенту значение типа float, и клиент сам занимается его переводом в строковое представление, а второе для клиента будет уже строкой, полученной преобразованием float на сервере. И то и другое должно быть сделано одним алгоритмом.
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36363934
Фотография Ggg_old
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
+1 в копилку АСА
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36371955
Фотография Badger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Забавно, что результаты теста на разных базах различаются так:
select convert(float,0.133),convert(char,convert(float,0.133))

ASA
0.133 .13300000131130219

ASE
.13300000000000001 .13300000000000001

MSSQL
0.13300000000000001 0.133
...
Рейтинг: 0 / 0
странности конвертации float в varchar
    #36372537
iLLer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Badger,

Дык потому что результат зависит от клиента, который показывает результат, и от его способностей по работе с плавающими запятыми.
Я делал тест на АСА9 в ISQL си-шной версии. Java версию интерактива не перевариваю.
...
Рейтинг: 0 / 0
27 сообщений из 27, показаны все 2 страниц
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / странности конвертации float в varchar
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]