powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Округление real vs double
9 сообщений из 9, страница 1 из 1
Округление real vs double
    #37003009
mwolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DB2 v8

Есть функция:
имя(параметры) RETURNS numeric(5, 2)

В ней объявлены параметры:
DECLARE totalScore DOUBLE default 0;
DECLARE counter INTEGER default 0;

В конце есть такое:
return round((totalScore/counter), 2);

При totalScore=12.1 и counter=4 ф-ция возвращает 3,02. Хотя 12.1/4=3.025 и при округлении должно быть 3,03.

Вычисляем:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
select
 12 . 1 /  4  as a1, --что есть
round(( 12 . 1  /  4 ),  2 ) as a2, --"обычное" округление
round((cast( 12 . 1  as double)/  4 . 0 ), 2 ) as a3, --округление дабла
round((cast( 12 . 1  as real)/  4 ),  2 ) as a4 --округление рила
from sysibm.SYSDUMMY1
--
 A1     A2     A3     A4    
 -----  -----  ----  ----- 
  3 , 025    3 , 03     3 , 02    3 , 03  

Есть идея поменять тип переменной totalScore с double на real, но мне бы всё-таки хотелось понять причины такого странного поведения. Заранее благодарю за подсказки
...
Рейтинг: 0 / 0
Округление real vs double
    #37003745
Ivan Ivanich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
"Хотя 12.1/4=3.025 и при округлении должно быть 3,03."

Вы уверены? Округления, они разные бывают.
...
Рейтинг: 0 / 0
Округление real vs double
    #37003749
Ivan Ivanich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...
Рейтинг: 0 / 0
Округление real vs double
    #37003950
mwolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ivan Ivanich"Хотя 12.1/4=3.025 и при округлении должно быть 3,03."

Вы уверены? Округления, они разные бывают.

У вас есть ещё какие-либо комментарии, кроме констатации факт о том, что существуют разные виды округления? Например, почему в случае double и real применяются разные округления? Я полагаю, это было бы более полезно, чем мериться датами, когда мы впервые узнали об этом занимательном факте.
...
Рейтинг: 0 / 0
Округление real vs double
    #37003989
Ivan Ivanich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mwolfУ вас есть ещё какие-либо комментарии, кроме констатации факт о том, что существуют разные виды округления? Например, почему в случае double и real применяются разные округления?

Я просто подумал, что Вы не знаете об этом факте, вот и удивляетесь. Если знаете, хорошо. Давайте поищем в мануалах вместе.
...
Рейтинг: 0 / 0
Округление real vs double
    #37004051
Mark Barinstein
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mwolfDB2 v8

Есть функция:
имя(параметры) RETURNS numeric(5, 2)

В ней объявлены параметры:
DECLARE totalScore DOUBLE default 0;
DECLARE counter INTEGER default 0;

В конце есть такое:
return round((totalScore/counter), 2);

При totalScore=12.1 и counter=4 ф-ция возвращает 3,02. Хотя 12.1/4=3.025 и при округлении должно быть 3,03.

Есть идея поменять тип переменной totalScore с double на real, но мне бы всё-таки хотелось понять причины такого странного поведения. Заранее благодарю за подсказкиБагофича это какая-то...
Если у вас надо получить numeric(5, 2), то используйте:
Код: plaintext
round(dec(totalScore/counter,  31 ,  26 ),  2 )
...
Рейтинг: 0 / 0
Округление real vs double
    #37004137
Ivan Ivanich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
round((cast(12.1 as decimal(5,2))/ 4), 2) as a5 --округление decimal тоже дал 3.03
на той же версии базы. отличается только от всех типов только округление double
...
Рейтинг: 0 / 0
Округление real vs double
    #37004781
golsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ответ в формате хранения числа в real и dooble.
Вкраце: число представлено ввиде показателя (степени) 2 и мантиссы - двоичной дроби.
Мантиссу нормализуют - за счет показателя добиваются, чтобы она начиналась с 1 и берут эту 1 "на ум". Это обеспечивает хранение 15-16 (для double) значащих цифр.

При таком подходе целая часть числа (в пределах значащих цифр) хранится точно, а вот дробные не зависимо от числа цифр - УВЫ не всегда.

Например:
0.1 вы не сможете представить в виде суммы A1/2 + A2/4 + A3/8+ ... + An/2^n,
где n-длина мантиссы в битах (для double n=53 или 54 точно не помню) и Ai = (0 или 1).

Поэтому вы делите на самом деле не 12.1, а что-то типа 12.09999...986 и соответственно в результате имеете 3.024999...

ЗЫ. Никогда не храните деньги в double / real. Или храните их в копейках / сантимах / центах
...
Рейтинг: 0 / 0
Округление real vs double
    #37004953
mwolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо всем ответившим.

В качестве решения буду кастить double во что-то приемлимое, скорее всего в numeric(5,3).

В ходе экспериментов выяснилось, что причина в том, что double зверски хранит числа. Не то, чтобы я этого не знал, просто не думал, что всё настолько плохо.

В качестве примера "багофич" пару результатов ф-ций:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
--неправильное округление:
sysibm.round((cast( 12 . 1  as double)/  4 ), 2 )
--
 3 , 02 

--приводим неизвестно что хранящий дабл к правоверному рилу
cast(cast( 12 . 1  as double)/  4  as real)
--
 3 , 0250000953674316 
--наблюдаем некоторый мусор

--попробуем округлить
sysibm.round(cast((cast( 12 . 1  as double)/  4 ) as real), 2 )
--
 3 , 0299999713897705 
--ААА!!! Я поламал округление! ВЗФ!

-- вот так будет в релизе
sysibm.round((cast((totalScore as numeric( 5 , 3 ))/ counter),  2 )

Ещё раз всем спасибо.

З.Ы. Хотя что произошло с округлением я так и не понял
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Округление real vs double
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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