powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / 0.1 + 0.2 = 0.3
24 сообщений из 24, страница 1 из 1
0.1 + 0.2 = 0.3
    #39685810
DFilushin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброе утро

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


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

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

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

Кстати, Firebird тоже корректно вычисляет
Код: plsql
1.
select 0.1 + 0.2 from rdb$database
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39685811
Фотография Щукина Анна
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DFilushin,
вы бы ещё указали типы данных в случае с ораклом и с ЯПами.... Если в ваших ЯПах это что-то из серии флоат (float), то ничего удивительно. Флоат - это приблизительный тип. Соответственно, и результат в нем будет - тоже приблизительный.
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39685812
DFilushin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Щукина Анна,

для питона набирал в консоли, без указания типов, он же с динам. типизацией
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39685813
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
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
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39685818
DFilushin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вячеслав Любомудров,

здесь вы указали тип принудительно
Какой механизм используется для простого "нетипизированного" вычисления?
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39685819
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А по умолчанию NUMBER со своей точностью 39-40 знаков
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
tst> set numwidth 42
tst> select .0987654321098765432109876543210987654321 from dual;

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

tst> select .09876543210987654321098765432109876543219 from dual;

.09876543210987654321098765432109876543219
------------------------------------------
 .0987654321098765432109876543210987654322
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39685824
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вячеслав ЛюбомудровА по умолчанию NUMBER А в PL/SQL ещё и PLS_INTEGER.
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39686022
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Щукина Анна Флоат - это приблизительный тип. Соответственно, и результат в нем будет - тоже приблизительный.
Это типа шутка такая была?
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39686031
IMNO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousЩукина Анна Флоат - это приблизительный тип. Соответственно, и результат в нем будет - тоже приблизительный.
Это типа шутка такая была?
Почему шутка? Флоат же аппаратный тип, а не программный. Из-за грубого округления в двоичной системе счисления и возникает неточность.
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39686034
Зашедший
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DFilushinВопрос возникает, какая разница в механизмах расчётов в СУБД и ЯП?
Как писать код на яве в оракле с оглядкой на эту проблему.У меня возникает другой вопрос - как работающий в IT человек может не знать отличий binary и decimal форматов? Про стандарт IEEE 754 не буду вспоминать уж.
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39686050
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
IMNOФлоат же аппаратный тип, а не программный. Из-за грубого округления в двоичной системе счисления и возникает неточность.
Рукалицо.
Не поверите - в современной вычислительной технике ВСЕ данные - двоичные, "программные" тоже.
Впрочем, про IEEE 754 тут уже напомнили - несведущим рекомендовал бы ознакомиться хотя бы поверхностно.
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39686097
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
в делфи тип currency подходит для денег
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39686105
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreymxв делфи тип currency подходит для денег
Для денег подойдет любая реализация fixed point, самая распространенная - представление в виде целого, помноженного на 10 в интересующей степени.
Из плавающих - подойдет реализация с десятичным порядком, к примеру - см. decimalXX из IEEE 754—2008, он же ISO/IEC/IEEE 60559:2011.
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39686483
Фотография Hett
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous,

С каких пор decimal с плавающей точкой?
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39686518
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HettС каких пор decimal с плавающей точкой?Decimal из sql и инженерный не одно и то же. А точке все равно, в чем плавать.
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39686528
Зашедший
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hettandrey_anonymous,
С каких пор decimal с плавающей точкой?Это уже становится не смешно. Позор какой-то, люди типа "работают" в IT и при этом не желают знать базовых стандартов данных
IEEE 754 указывает следующие типы форматов с плавающей запятой:
Стандарт-binary16
-binary32
-binary64
-binary128
-binary256
-decimal32
-decimal64
-decimal128
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39686540
Excession
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DFilushinДоброе утро
на oracle выдаёт корректный ответ 0.3

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

Теперь поделим 1 на 3 в десятичной системе отсчета и о ужас получится 0.3333333333 ну и так далее в периоде,
вах вах вах в одной системе отсчета так красиво 0.1, а в другой 0.(3) как же так? :)
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39687020
IMNO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
До этой темы я докумал, что понимаю как хранятся числа.
Перечитал IEEE754. Ещё раз перечитал. Погуглил статьи про фиксированную/плавающую запятую.
Перечитал стандарт ещё несколько раз.
Теперь я вообще ничего не понимаю.

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

Код: plsql
1.
select .1d+.2d from dual;



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

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

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
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 в двоичную систему нормально не переводится.
Нужно выбрать точность перевода. Отсюда и "четверка" в примере выше.

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

Код: plsql
1.
select .1+.2 from dual;



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

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

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

Короче, что происходит?
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39687051
Зашедший
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
IMNOВедь binaryXX почти тоже самое что и decimalXX.
У них только основание различается, то есть тоже должна быть погрешность.Децимал - даже близко не то же самое. 0.1 с десятичным основанием переведется как 1х10^-1
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39687170
Excession
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
IMNOПочему результат без "непредвиденной" дроби? Что за магия?
Магия типа Number в Oracle
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39687187
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
IMNO
Код: plsql
1.
select .1d+.2d from dual;



Здесь результат принудительно приводится к типу decimalXX, который из IEEE754.Все-таки открывай учебник по продукту с которым работаешь/разбираешься
D - это не от Decimal, а от Double
Есть еще F
Код: plsql
1.
2.
3.
4.
5.
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Но почему "правильный результат" получился в этом примере?

Код: plsql
1.
select .1+.2 from dual;



Почему результат без "непредвиденной" дроби? Что за магия?
Потому что тип NUMBER хранится не по основанию 2, а по основанию 100
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39688641
IMNO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вячеслав Любомудров как оно укладывается в 64 Double-precision floating-point format можно посмотреть, например, тут

Крутая ссылка, спасибо.

Вячеслав Любомудров
IMNOНо почему "правильный результат" получился в этом примере?

Код: plsql
1.
select .1+.2 from dual;



Почему результат без "непредвиденной" дроби? Что за магия?
Потому что тип NUMBER хранится не по основанию 2, а по основанию 100

Так.
Получается, что в Oracle:
1. BINARY_FLOAT и BINARY_DOUBLE - это binaryXX из IEEE754
2. NUMBER - это decimalXX из IEEE754

Все три типа "программные", а не "аппаратные".

Немного отступления. Что я имею ввиду, когда пишу "стандарт".
Этакий чёрный ящик, у которого есть входы и выходы. Совершенно не важно, как данные хранятся внутри(программно, аппаратно или ещё как-нибудь), главное чтобы на выходе результат был такой, какой описан в стандарте.

То есть binaryXX говорит, что может должна быть неточность после N-ого знака.
DecimalXX говорит, что до N-ой позиции неточности быть не должно.
То есть как писал andrey_anonymous, тот же decimalXX всё равно хранится как двоичный код, но результат должен выдаваться точный.
То есть при использовании типа decimalXX отрабатывает алгоритм который сглаживает неточность хранения чисел в двоичном коде.

Поправьте пожалуйста, если что не так.
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39688646
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Оракловый NUMBER не имеет никакого отношения к IEEE754 и ссылочку на его потроха тебе приведена
Больше всего оно похоже на BCD ( https://ru.wikipedia.org/wiki/Двоично-десятичный_код), бывший популярен во многих финансово-ориентированных языках (Cobol, PL/1), только основание не 10, а 100
...
Рейтинг: 0 / 0
0.1 + 0.2 = 0.3
    #39688782
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
IMNOПоправьте пожалуйста, если что не так.
Поправляю.
Числа с плавающей точкой хранятся как пара целых чисел. Целых, обратите внимание.
Все истории про неточности - это истории про множества представимых чисел и выбор ближайшего представимого для непредставимого (правила округления).
А вся разница между binary, decimal и тем же oracle number - это основание логарифма. Десятичный или двойка. Все остальное - в контексте обсуждаемой проблемы от лукавого.
"стреляет" основание логарифма при нормализации. Не будь ее - не стреляло бы, но имели бы место другие спецэффекты.
И еще. Разделение на "программные" и "аппаратные" в том пещерном понимании, которое тут демонстрировалось - суть фейк.
...
Рейтинг: 0 / 0
24 сообщений из 24, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / 0.1 + 0.2 = 0.3
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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