powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / вы думаете что 1+(-1) = 0? а вот и нет
25 сообщений из 76, страница 1 из 4
вы думаете что 1+(-1) = 0? а вот и нет
    #39478820
bigker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
не могу найти на форуме. но проблема старая и я был уверен что давно решенная
Oracle 11.2.0.3.0 64 bit

ситуация следующая. есть средних размеров таблица. начиная с определенного момента запрос
вида
Код: sql
1.
select   t.num,  sum(t.num)over() nsum from mytable t where ....


стал выдавать следующие данные:
Код: plaintext
1.
2.
3.
          num         nsum
1     -17,3563     -2,3E-37
2      17,3563     -2,3E-37
что в общем приводит к неприятным последствиям

с чем связан этот баг в целом понятно - особенности хранения вещественных чисел. вопрос в другом, как с этим бороться? получается что ни в одном запросе нельзя использовать суммирование без округления? результат не гарантирован. или архитектурно прописывать всегда точность хранения....
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39478825
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bigkerс чем связан этот баг в целом понятноЗаблуждаешься.
RTFM set numwidth, DUMP, TO_CHAR
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39478862
MaximaXXL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bigker,

Странно, у меня вот так например:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
with t as (select -17.3563 num from dual union all
select 17.3563 from dual )

select   t.num,  sum(t.num)over() nsum from t

NUM	     NSUM
-17.3563	0
17.3563  	0

2 rows selected.
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39478869
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximaXXLСтранно, у меня вот так например:А надо так:
Код: plsql
1.
-17.3563-2.3e-37
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39478884
IgorSm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Как раз на тему "всегда ли определять Number?"
http://www.sql.ru/forum/1264000-1/vsegda-li-opredelyat-number
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39478932
bigker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну вобщем я понимаю так - то что я не вижу знака в 37 разряде после запятой - не значит что его там нет. и нужно было озаботиться округлением (trunc) самому. либо при записи данных, либо при суммировании. Все вокруг сплошной обман =)
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39478940
bigkerНу вобщем я понимаю так - то что я не вижу знака в 37 разряде после запятой - не значит что его там нет. и нужно было озаботиться округлением
Озаботиться нужно заданием необходимых масштаба и точности для поля с типом данных NUMBER, а не вбиванием костылей в виде округления и усечение имеющихся данных.
И, да (поскольку структура таблицы не показана) - избегать применения машинных числовых типов (binary_float & binary_double) если требуется фиксированная точность вычислений.
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39478941
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bigkerНу вобщем я понимаю так - то что я не вижу знака в 37 разряде после запятой - не значит что его там нет.Да.
bigkerокруглением (trunc)Ты уж определись.
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39478943
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
молчать и слушать, молчать и слуизбегать применения машинных числовых типов (binary_float & binary_double)Ни один из этих типов не может дать наблюдаемой здесь точности (погрешности)
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39478973
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Elicмолчать и слушать, молчать и слуизбегать применения машинных числовых типов (binary_float & binary_double)Ни один из этих типов не может дать наблюдаемой здесь точности (погрешности)
Даже binary_double легко дает гораздо большую погрешность:
Код: plsql
1.
2.
3.
4.
5.
6.
SQL>select to_char((1+power(2,-54)) - cast(cast(1+power(2,-54) as binary_double) as number),'0.99999eeee') err
from dual;

ERR         
-------------
  5.55112E-17 
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39479062
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousгораздо большую погрешностьпредлагаю задуматься над словом "наблюдаемой", сравнить порядок погрешности и исходной величины.
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39479066
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
-2-andrey_anonymousгораздо большую погрешностьпредлагаю задуматься над словом "наблюдаемой", сравнить порядок погрешности и исходной величины.
Раскройте пожалуйста свою мысль.
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39479067
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousРаскройте пожалуйста свою мысль.Сперва ты: ты мне возражал или же подтверждал мой тезис своим примером?
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39479068
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous-2-пропущено...
предлагаю задуматься над словом "наблюдаемой", сравнить порядок погрешности и исходной величины.
Раскройте пожалуйста свою мысль.Между 10 1 и 10 -38 требуется точность 40 значащих цифр. binary_double дает до 18 десятичных знаков.
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39479072
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
-2-andrey_anonymousпропущено...

Раскройте пожалуйста свою мысль.Между 10 1 и 10 -38 требуется точность 40 значащих цифр. binary_double дает до 18 десятичных знаков.
И что из этого следует?
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39479085
kernA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bigkerне могу найти на форуме. но проблема старая и я был уверен что давно решенная
Oracle 11.2.0.3.0 64 bit

пропущено...

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

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
create table t123(a number, b number);

insert into t123 values (1,1);
insert into t123 values (-1/3,2);
insert into t123 values (-1/3,3);
insert into t123 values (-1/3,4);

select b, a, sum(a) over () nsum from t123



Код: plaintext
1.
2.
b  a  nsum
1  1  3,4E-39

По логике, после вычисления надо округлять.
Могут не сойтись условия a-b=0, либо минус между множествами.
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39479094
kernA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kernAМогут не сойтись условия a-b=0.

* имелось ввиду значения из одной колонки, сгруппированные по определённому признаку
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39479112
dbpatch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous-2-пропущено...
Между 10 1 и 10 -38 требуется точность 40 значащих цифр. binary_double дает до 18 десятичных знаков.
И что из этого следует?

следует то, что некорректно сравнивать граничные number и binary_float, в первый влазит намного больше "информации" - значащих цифр, разница между ними будет всегда

проблема же автора скорее из отряда того, что у него клиенские double/float (а это очень распостраненная практика - преобразовывать number, который base100 разновидность BCD в типы IEEE на клиенте, ибо там других типов нет) пишутся в базу данных без специальной коррекции, в результате он наступает на проблему

http://0.30000000000000004.com/

и тут ему только в trunc()/round(), ну и в dump() для полного просвещения, сама же СУБД тут абсолютно ни при чем.
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39479187
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbpatchandrey_anonymousпропущено...

И что из этого следует?

следует то, что некорректно сравнивать граничные number и binary_float
:)

Фикус немного в другом.
number в oracle имеет не только десятичную мантиссу, но и, что более важно, десятичный порядок.
Числа, представленные в IEEE-754, имеют двоичный порядок.
И тут наступает смешная штука - множества представимых чисел в этих представлениях тупо не совпадают .
И чем больше порядок - тем больше расстояние между представимыми числами, и, следовательно, больше абсолютная погрешность.
В итоге, сохраняя IEEE-754 (а они бывают 32, 64, и 80 бит) во вроде бы более точный number, получаем по факту потерю точности, поскольку в number не всегда возможно представить значение double.
Потому и ввели в 12с binary_double и binary_float, чтобы классические приложения могли хранить данные без преобразования и не "наступать".
И в этой связи мне показался слегка странным данный тут совет избегать этих типов.
Если что - устриц ел, в смысле - приходилось как-то плотно заниматься "самопальным" преобразованиями из IEEE-754 в number и обратно.
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39479198
dbpatch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousdbpatchпропущено...


следует то, что некорректно сравнивать граничные number и binary_float
:)

Фикус немного в другом.
number в oracle имеет не только десятичную мантиссу, но и, что более важно, десятичный порядок.
Числа, представленные в IEEE-754, имеют двоичный порядок.

не совсем десятичный, там base100. но с натяжкой ок, можно считать десятичным :)
http://www.orafaq.com/wiki/Number#Internal_storage


andrey_anonymousИ тут наступает смешная штука - множества представимых чисел в этих представлениях тупо не совпадают .
И чем больше порядок - тем больше расстояние между представимыми числами, и, следовательно, больше абсолютная погрешность.
В итоге, сохраняя IEEE-754 (а они бывают 32, 64, и 80 бит) во вроде бы более точный number, получаем по факту потерю точности, поскольку в number не всегда возможно представить значение double.

а не наоборот ???

andrey_anonymousПотому и ввели в 12с binary_double и binary_float, чтобы классические приложения могли хранить данные без преобразования и не "наступать".
сомнительно, ИМХО это было скорее для вопроса перфоманса.

andrey_anonymousИ в этой связи мне показался слегка странным данный тут совет избегать этих типов.\
Oracle в подавляющем большинстве случаев используется для подсчета и хранения денег, а использование там нативного
double вообще говоря преступление с т.з. бухгалтерий всяких (если у тебя нет библиотеки для "нормализации" копеек после умножений и делений).

в IBM вообще есть целая библиотека для "правильного" подсчета денег https://github.com/libdfp/libdfp
даром что ей никто не пользуется (в Java и .NET тоже есть имплементации, тоже непопулярные).

andrey_anonymous Если что - устриц ел, в смысле - приходилось как-то плотно заниматься "самопальным" преобразованиями из IEEE-754 в number и обратно.
да нет там никаких устриц, задача для начального уровня. я с ней столкнулся практически на второй неделе после того, как вообще начал работать программистом - мне принесли два отчета где цифры Итого не сходились.

странно, что неофиты до сих пор наступают на такие грабли, и никто не решил проблему системно
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39479211
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbpatchне совсем десятичный, там base100. но с натяжкой ок, можно считать десятичным :)

Сам когда-то так полагал (и вроде даже писал на этом форуме).
Но там чистый BCD.
Если конвертировать по-байтно - то да, удобно в сторичной считать.
Однако в контексте беседы это вообще не имеет значения.

dbpatchandrey_anonymousИ тут наступает смешная штука - множества представимых чисел в этих представлениях тупо не совпадают .
И чем больше порядок - тем больше расстояние между представимыми числами, и, следовательно, больше абсолютная погрешность.
В итоге, сохраняя IEEE-754 (а они бывают 32, 64, и 80 бит) во вроде бы более точный number, получаем по факту потерю точности, поскольку в number не всегда возможно представить значение double.
а не наоборот ???

Что конкретно наоборот?
Расстояние между представимыми числами, точность или невозможность представить IEEE-754 в number?

dbpatchandrey_anonymousПотому и ввели в 12с binary_double и binary_float, чтобы классические приложения могли хранить данные без преобразования и не "наступать".
сомнительно, ИМХО это было скорее для вопроса перфоманса.

Что-то я сомневаюсь относительно заметного "перформанс гаин" :)

dbpatchстранно, что неофиты до сих пор наступают на такие грабли, и никто не решил проблему системно
Так нет тут "системной проблемы", потому и не решают.
Всего лишь особенности машинных вычислений, которые по идее должны преподаваться на профильных курсах.
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39479256
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот более "чистая" иллюстрация несовпадения представимых множеств IEEE-754 и number:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
clear
set numwidth 20
with t as (
select 1.000000000000001d bd
     , cast(1.000000000000001d as number) bd2n 
     , 1.000000000000001 n
from dual
connect by level < 10000
)
select min(n) as "Number", sum(n) "Number Calc", min(bd) "IEEE-754 double  ", sum(bd) "IEEE754 double Calc", min(bd2n) "IEEE->Number", sum(bd2n) "IEEE->Number Calc" from t
;

              Number          Number Calc IEEE-754 double   IEEE754 double Calc         IEEE->Number    IEEE->Number Calc
-------------------- -------------------- ----------------- ------------------- -------------------- --------------------
   1.000000000000001 9999.000000000009999 1.000000000000001 9999.000000000002     1.0000000000000011 9999.0000000000109989 


Как видно и примера, само по себе десятичное 1.000000000000001 представимо в number, но не представимо в double, хотя и делает вид, что представимо :)
Ближайшее к 1.000000000000001 представимое в double - это '3FF0000000000005', однако это НЕ 1.000000000000001 и при конвертации double->number получаем ближайшее представимое в number - 1.0000000000000011

Одновременно иллюстрация про точность.
Как видим, суммирование в number дает корректный результат.
Однако суммирование в double идет с потерей точности, поскольку мантиссы в 6.5 байт для представления суммы не хватает.
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39479268
dbpatch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousdbpatchне совсем десятичный, там base100. но с натяжкой ок, можно считать десятичным :)

Сам когда-то так полагал (и вроде даже писал на этом форуме).
Но там чистый BCD.

ой да ладно. base100 это и разновидность BCD, но если мы говорим про IBM варианты, то .... блин, да нет понятия чистый BCD
https://en.wikipedia.org/wiki/Binary-coded_decimal



andrey_anonymousdbpatchа не наоборот ???

Что конкретно наоборот?
Расстояние между представимыми числами, точность или невозможность представить IEEE-754 в number?
всякий IEEE-754 можно представить как number, но не наоборот.
ты говорил что как раз не всякий IEEE-754 можно в number, что не есть научно


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

это не техническая системная проблема, а проблема организационная.

практически все актуальные языки программирования имеют реализацию Money/Currency или подобного, от Fixed pointer до BCD вариаций, но этим никто не пользуются, все почему-то считают деньги через double, который без специальных библиотек можно использовать лишь для инженерных/научных расчетов, но никак не для бухгалтерий

есть даже специальный вид консалтинга - приходят и начинают код "линтать", на предмет некорректного использования double (первым делом ищут операторы деления и умножения, находят практически каждый раз в новом коде)
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39479274
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbpatchandrey_anonymousпропущено...
Сам когда-то так полагал (и вроде даже писал на этом форуме).
Но там чистый BCD.
ой да ладно. base100 это и разновидность BCD

Ну покажи вариант BCD, который нельзя назвать "BASE 100" :)

dbpatchвсякий IEEE-754 можно представить как number, но не наоборот.

Неправда ваша.
Пример - выше :)
Что до научности - то независимо от системы счисления множество вещественных чисел нельзя представить ни в одном из машинных представлений уже просто ввиду перечислимости представимых множеств.
Из первого попавшегося можно почитать здесь:
http://www.softelectro.ru/ieee754.html
7.4 Точность представления вещественных чисел в формате IEEE754

А в обсуждаемом случае имеем ошибку преобразования из одного представления в другое просто ввиду несовпадения множеств представимых чисел.
...
Рейтинг: 0 / 0
вы думаете что 1+(-1) = 0? а вот и нет
    #39479281
dbpatch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousdbpatchпропущено...

ой да ладно. base100 это и разновидность BCD

Ну покажи вариант BCD, который нельзя назвать "BASE 100" :)


Я дал ссылку на википедию, все описанные там варианты BCD - не base 100.


andrey_anonymousdbpatchвсякий IEEE-754 можно представить как number, но не наоборот.

Неправда ваша.
Пример - выше :)

какой такой пример? с power? ну так power для double выдает искаженный результат, но это не означает, что существует
какое-то представимое в double число, которое нельзя воткнуть в number без потери значимых цифр.

или еще раз - число, в студию, которое можно присвоить в double, но нельзя такое-же число получить в number без искажений :)

andrey_anonymousЧто до научности - то независимо от системы счисления множество вещественных чисел нельзя представить ни в одном из машинных представлений уже просто ввиду перечислимости представимых множеств.
Из первого попавшегося можно почитать здесь:
http://www.softelectro.ru/ieee754.html
7.4 Точность представления вещественных чисел в формате IEEE754

А в обсуждаемом случае имеем ошибку преобразования из одного представления в другое просто ввиду несовпадения множеств представимых чисел.

вот жеж блин :\

где я говорил, что бесконечное множество вещественных чисел можно представить в number?
число 0.3(3), как результат 1/3 нельзя представить ни в double, ни в number, без потери точности, это и ежу понятно,

речь же была про другое, про то, что не всякий double можно в number - я к этому утверждению (ложному) и придрался

говоря проще - я утверждал (вернее предпологаю), что все конечное множество числел double можно поместить в множество number.


вот и прошу опровергнуть оное, примерами непомещаемых чисел
...
Рейтинг: 0 / 0
25 сообщений из 76, страница 1 из 4
Форумы / Oracle [игнор отключен] [закрыт для гостей] / вы думаете что 1+(-1) = 0? а вот и нет
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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