Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 0.1 + 0.2 = 0.3  [new]
DFilushin
Member

Откуда: Новосибирск
Сообщений: 239
Доброе утро

немного пятничная тема.
Запрос
select 0.1 + 0.2 from dual

на oracle выдаёт корректный ответ 0.3

На Python, Java, Perl и других языках
.1 + .2
0.30000000000000004

Вопрос возникает, какая разница в механизмах расчётов в СУБД и ЯП?
Как писать код на яве в оракле с оглядкой на эту проблему.

Кстати, Firebird тоже корректно вычисляет
select 0.1 + 0.2 from rdb$database
10 авг 18, 05:40    [21637090]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
Щукина Анна
Member

Откуда:
Сообщений: 940
DFilushin,
вы бы ещё указали типы данных в случае с ораклом и с ЯПами.... Если в ваших ЯПах это что-то из серии флоат (float), то ничего удивительно. Флоат - это приблизительный тип. Соответственно, и результат в нем будет - тоже приблизительный.

10 авг 18, 05:57    [21637092]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
DFilushin
Member

Откуда: Новосибирск
Сообщений: 239
Щукина Анна,

для питона набирал в консоли, без указания типов, он же с динам. типизацией
10 авг 18, 06:05    [21637093]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
Вячеслав Любомудров
Member

Откуда: Владивосток
Сообщений: 17726
tst> select .1+.2 from dual;

       .1+.2
------------
          .3

tst> select .1d+.2d from dual;

     .1D+.2D
------------
    3.0E-001

tst> set numwidth 40
tst> select .1d+.2d from dual;

                                 .1D+.2D
----------------------------------------
                 3.0000000000000004E-001
10 авг 18, 06:14    [21637094]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
DFilushin
Member

Откуда: Новосибирск
Сообщений: 239
Вячеслав Любомудров,

здесь вы указали тип принудительно
Какой механизм используется для простого "нетипизированного" вычисления?
10 авг 18, 06:41    [21637099]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
Вячеслав Любомудров
Member

Откуда: Владивосток
Сообщений: 17726
А по умолчанию NUMBER со своей точностью 39-40 знаков
tst> set numwidth 42
tst> select .0987654321098765432109876543210987654321 from dual;

 .0987654321098765432109876543210987654321
------------------------------------------
 .0987654321098765432109876543210987654321

tst> select .09876543210987654321098765432109876543219 from dual;

.09876543210987654321098765432109876543219
------------------------------------------
 .0987654321098765432109876543210987654322
10 авг 18, 07:15    [21637105]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
Elic
Member

Откуда: 1984. Выбраковка финно-угром продолжается. КЯЗ
Сообщений: 28112
Вячеслав Любомудров
А по умолчанию NUMBER
А в PL/SQL ещё и PLS_INTEGER.
10 авг 18, 07:22    [21637111]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 16605
Щукина Анна
Флоат - это приблизительный тип. Соответственно, и результат в нем будет - тоже приблизительный.

Это типа шутка такая была?
10 авг 18, 12:48    [21637618]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
IMNO
Member

Откуда:
Сообщений: 49
andrey_anonymous
Щукина Анна
Флоат - это приблизительный тип. Соответственно, и результат в нем будет - тоже приблизительный.

Это типа шутка такая была?

Почему шутка? Флоат же аппаратный тип, а не программный. Из-за грубого округления в двоичной системе счисления и возникает неточность.
10 авг 18, 12:57    [21637638]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
Зашедший
Member

Откуда: Москва
Сообщений: 3903
DFilushin
Вопрос возникает, какая разница в механизмах расчётов в СУБД и ЯП?
Как писать код на яве в оракле с оглядкой на эту проблему.
У меня возникает другой вопрос - как работающий в IT человек может не знать отличий binary и decimal форматов? Про стандарт IEEE 754 не буду вспоминать уж.
10 авг 18, 13:02    [21637654]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 16605
IMNO
Флоат же аппаратный тип, а не программный. Из-за грубого округления в двоичной системе счисления и возникает неточность.

Рукалицо.
Не поверите - в современной вычислительной технике ВСЕ данные - двоичные, "программные" тоже.
Впрочем, про IEEE 754 тут уже напомнили - несведущим рекомендовал бы ознакомиться хотя бы поверхностно.
10 авг 18, 13:16    [21637701]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 47627
в делфи тип currency подходит для денег
10 авг 18, 14:42    [21637963]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 16605
andreymx
в делфи тип currency подходит для денег

Для денег подойдет любая реализация fixed point, самая распространенная - представление в виде целого, помноженного на 10 в интересующей степени.
Из плавающих - подойдет реализация с десятичным порядком, к примеру - см. decimalXX из IEEE 754—2008, он же ISO/IEC/IEEE 60559:2011.
10 авг 18, 14:55    [21638006]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
Hett
Member

Откуда: Бийск, Новосибирск
Сообщений: 13059
andrey_anonymous,

С каких пор decimal с плавающей точкой?
12 авг 18, 09:03    [21639022]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
-2-
Member

Откуда:
Сообщений: 13672
Hett
С каких пор decimal с плавающей точкой?
Decimal из sql и инженерный не одно и то же. А точке все равно, в чем плавать.
12 авг 18, 11:31    [21639083]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
Зашедший
Member

Откуда: Москва
Сообщений: 3903
Hett
andrey_anonymous,
С каких пор decimal с плавающей точкой?
Это уже становится не смешно. Позор какой-то, люди типа "работают" в IT и при этом не желают знать базовых стандартов данных
IEEE 754 указывает следующие типы форматов с плавающей запятой:
Стандарт
-binary16
-binary32
-binary64
-binary128
-binary256
-decimal32
-decimal64
-decimal128

12 авг 18, 12:27    [21639121]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
Excession
Member

Откуда:
Сообщений: 25
DFilushin
Доброе утро
на oracle выдаёт корректный ответ 0.3

Давай поделим 1 на 3 в троичной системе отсчета, что получится?
Получится в естественной форме записи числа 0.1 в троичной системе отсчета.

Теперь поделим 1 на 3 в десятичной системе отсчета и о ужас получится 0.3333333333 ну и так далее в периоде,
вах вах вах в одной системе отсчета так красиво 0.1, а в другой 0.(3) как же так? :)
12 авг 18, 13:52    [21639161]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
IMNO
Member

Откуда:
Сообщений: 49
До этой темы я докумал, что понимаю как хранятся числа.
Перечитал IEEE754. Ещё раз перечитал. Погуглил статьи про фиксированную/плавающую запятую.
Перечитал стандарт ещё несколько раз.
Теперь я вообще ничего не понимаю.

Вячеслав Любомудров приводил пример.

select .1d+.2d from dual;


Здесь результат принудительно приводится к типу decimalXX, который из IEEE754.

Откуда берётся "четвёрка":
Переведём 0.1 в двоичную систему счисления:

0.1 * 2 = 0.2
0.2 * 2 = 0.4
0.4 * 2 = 0.8
0.8 * 2 = 1.6
0.6 * 2 = 1.2
0.2 * 2 = 0.4
0.4 * 2 = 0.8
0.8 * 2 = 1.6
0.6 * 2 = 1.2


Дальше можно не продолжать.
Результат: 0.1 = 0.000110011
Можно заметить что 0011 в периоде.
То есть как и ожидалось, 0.1 в двоичную систему нормально не переводится.
Нужно выбрать точность перевода. Отсюда и "четверка" в примере выше.

Но почему "правильный результат" получился в этом примере?

select .1+.2 from dual;


Почему результат без "непредвиденной" дроби? Что за магия?

Зашедший писал:
Зашедший
не знать отличий binary и decimal


То есть могу предположить, что во втором примере(второй пример в моем сообщении) тип binaryXX.
Тогда я вообще ничего не понимаю. Ведь binaryXX почти тоже самое что и decimalXX.
У них только основание различается, то есть тоже должна быть погрешность.

Короче, что происходит?
13 авг 18, 17:17    [21640873]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
Зашедший
Member

Откуда: Москва
Сообщений: 3903
IMNO
Ведь binaryXX почти тоже самое что и decimalXX.
У них только основание различается, то есть тоже должна быть погрешность.
Децимал - даже близко не то же самое. 0.1 с десятичным основанием переведется как 1х10^-1
13 авг 18, 18:28    [21640988]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
Excession
Member

Откуда:
Сообщений: 25
IMNO
Почему результат без "непредвиденной" дроби? Что за магия?

Магия типа Number в Oracle
13 авг 18, 23:35    [21641211]     Ответить | Цитировать Сообщить модератору
 Re: 0.1 + 0.2 = 0.3  [new]
Вячеслав Любомудров
Member

Откуда: Владивосток
Сообщений: 17726
IMNO
select .1d+.2d from dual;


Здесь результат принудительно приводится к типу decimalXX, который из IEEE754.
Все-таки открывай учебник по продукту с которым работаешь/разбираешься
D - это не от Decimal, а от Double
+ Есть еще F
tst> select .1f+.2f from dual;

                                   .1F+.2F
------------------------------------------
                           3.00000012E-001

IMNO
Переведём 0.1 в двоичную систему счисления:

Результат: 0.1 = 0.000110011
Можно заметить что 0011 в периоде.
Ну, в общем, чем больше этих периодов, том точнее приближение, как оно укладывается в 64 Double-precision floating-point format можно посмотреть, например, тут
IMNO
Но почему "правильный результат" получился в этом примере?

select .1+.2 from dual;


Почему результат без "непредвиденной" дроби? Что за магия?
Потому что тип NUMBER хранится не по основанию 2, а по основанию 100
вчера, 04:24    [21641249]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить