powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Округление :|
20 сообщений из 20, страница 1 из 1
Округление :|
    #39475990
Luke221
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.

Помогите, пожалуйста, правильно округлить.

Сервер 2.5, диалект 3

select cast(27043022.5 as double precision) / cast(100 as double precision) from rdb$database

получаем результат 270430.224999999977 , при математическом округлении на 2 знаков после запятой получаем 270430.22, а нужно 270430.23 .
...
Рейтинг: 0 / 0
Округление :|
    #39475998
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Luke221,

не понятно по каким критериям вы хотите округлить. Как сервер поймёт это?
...
Рейтинг: 0 / 0
Округление :|
    #39475999
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Luke221,

В FB2.5 есть встроенная функция ROUND (number [, scale]).
...
Рейтинг: 0 / 0
Округление :|
    #39476005
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Когда-то заморачивался округлением вверх на сервере, родил вот такую процедуру.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
create or alter procedure ROUNDUP (
    AI numeric(18,2),
    ST integer)
returns (
    RESULT integer)
AS
declare variable st2 integer;
begin
  --
  -- Округляем до ST[EP] вверх.
  -- На входе нумерик а не integer потому что округляем после деления/умножения
  -- а если результат покастить к целому - то он в процессе каста округляется
  -- до ближайшего целого, чего как раз и хочется избежать
  --
  st2 = cast( (st / 2) as integer);
  if ( ((AI / st) * st) <> (cast((AI / st) as integer) * st) )
    then RESULT = cast(((AI-st2) / st) as integer) * st + st;
    else RESULT = AI;
  suspend;
end
...
Рейтинг: 0 / 0
Округление :|
    #39476012
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как вариант:
Код: sql
1.
SELECT Floor(Cast(27043022.5 as double precision) + 0.5) / 100 FROM RDB$DATABASE
...
Рейтинг: 0 / 0
Округление :|
    #39476014
Luke221
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Симонов ДенисLuke221,

не понятно по каким критериям вы хотите округлить. Как сервер поймёт это?

Есть 2 числа 27043022.5 и 100. При делении первого на второе результат 270430.225 , при округлении до 2 знаков после запятой получается 270430.23

Что делает Firebird:

select round(cast(27043022.5 as double precision) / cast(100 as double precision), 2) from rdb$database

Результат: 270430.22000000003
...
Рейтинг: 0 / 0
Округление :|
    #39476017
Luke221
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
rdb_devКак вариант:
Код: sql
1.
SELECT Floor(Cast(27043022.5 as double precision) + 0.5) / 100 FROM RDB$DATABASE



первое число - переменная, костылик +0.5 не прокатит для любых чисел
...
Рейтинг: 0 / 0
Округление :|
    #39476024
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Luke221, fraks

никакое округление вверх тут не поможет. Проблема автора в использовании типов с плавающей точкой
...
Рейтинг: 0 / 0
Округление :|
    #39476027
Luke221
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
fraksLuke221,

В FB2.5 есть встроенная функция ROUND (number [, scale]).

round как раз правильно работает, именно поэтому я и не упомянул. Неверный результат получается как раз при делении на 100 из-за особенностей Firebird с 9999999 в периоде
...
Рейтинг: 0 / 0
Округление :|
    #39476029
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Luke221первое число - переменная, костылик +0.5 не прокатит для любых чиселЧой-то не прокатит? Тебе же сначала надо округлить до целого, а только затем делить на 100? Дополнение на 0.5, с последующим отбрасыванием дробной части, очень даже прокатит, если при попадании в половину целого тебе надо округлять в большую сторону, а не в зависимости от четности/нечетности целого!
...
Рейтинг: 0 / 0
Округление :|
    #39476044
Luke221
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
rdb_devLuke221первое число - переменная, костылик +0.5 не прокатит для любых чиселЧой-то не прокатит? Тебе же сначала надо округлить до целого, а только затем делить на 100? Дополнение на 0.5, с последующим отбрасыванием дробной части, очень даже прокатит, если при попадании в половину целого тебе надо округлять в большую сторону, а не в зависимости от четности/нечетности целого!

не совсем...
ваш метод:
SELECT Floor(Cast(27043022.55 as double precision) + 0.5) / cast(100.0 as double precision) FROM RDB$DATABASE

дает 270430.23

а нужно:
27043022.55 / 100 = 270430.2255
...
Рейтинг: 0 / 0
Округление :|
    #39476045
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Luke221Неверный результат получается как раз при делении на 100 из-за особенностей Firebird с 9999999 в периодеRTFM double precision
...
Рейтинг: 0 / 0
Округление :|
    #39476046
Luke221
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Luke221rdb_devпропущено...
Чой-то не прокатит? Тебе же сначала надо округлить до целого, а только затем делить на 100? Дополнение на 0.5, с последующим отбрасыванием дробной части, очень даже прокатит, если при попадании в половину целого тебе надо округлять в большую сторону, а не в зависимости от четности/нечетности целого!

не совсем...
ваш метод:
SELECT Floor(Cast(27043022.55 as double precision) + 0.5) / cast(100.0 as double precision) FROM RDB$DATABASE

дает 270430.23

а нужно:
27043022.55 / 100 = 270430.2255

Тут я уже напутал) Результат при округлении до 2 знаков как раз 270430.23

p.s.> вроде прокатывает
...
Рейтинг: 0 / 0
Округление :|
    #39476049
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Luke221а нужно:
27043022.55 / 100 = 270430.2255
никак такое не получится, потому что по нормальному выходит
select cast(27043022.5 as numeric(18,2)) / cast(100 as numeric(18,2)) from rdb$database
270430,2250

откуда из 270430.224999999977 в 4м разряде после запятой получится 5 - непонятно.

Читать
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=374
и
http://www.delphikingdom.com/asp/viewitem.asp?catalogID=1217
...
Рейтинг: 0 / 0
Округление :|
    #39476060
Luke221
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kdvLuke221а нужно:
27043022.55 / 100 = 270430.2255
никак такое не получится, потому что по нормальному выходит
select cast(27043022.5 as numeric(18,2)) / cast(100 as numeric(18,2)) from rdb$database
270430,2250

откуда из 270430.224999999977 в 4м разряде после запятой получится 5 - непонятно.

Читать
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=374
и
http://www.delphikingdom.com/asp/viewitem.asp?catalogID=1217

потому что в моем 2 примере

select cast(27043022.55 as numeric(18,2)) / cast(100 as numeric(18,2)) from rdb$database
...
Рейтинг: 0 / 0
Округление :|
    #39476068
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Luke221,

да пофиг. читайте те 2 статьи.
...
Рейтинг: 0 / 0
Округление :|
    #39476084
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Luke221,

ещё раз повторяю проблема в использовании типов с плавающей точкой. Ну не возможно работать с double precision без ошибок округления. Поэтому пока вариант только один переходить на фиксированную точку. Выйдет 4.0 там можно развлекаться с DECFLOAT
...
Рейтинг: 0 / 0
Округление :|
    #39476088
Luke221
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Симонов ДенисLuke221,

ещё раз повторяю проблема в использовании типов с плавающей точкой. Ну не возможно работать с double precision без ошибок округления. Поэтому пока вариант только один переходить на фиксированную точку. Выйдет 4.0 там можно развлекаться с DECFLOAT

Проблема с фиксированной точкой другая - переполнение при умножении (там на самом деле сложнее формула)

kdvLuke221,

да пофиг. читайте те 2 статьи.

Спасибо за статьи

rdb_devКак вариант:
Код: sql
1.
SELECT Floor(Cast(27043022.5 as double precision) + 0.5) / 100 FROM RDB$DATABASE



Спасибо. Ваш метод и правда работает!

select round(round(cast(27043022.5 as double precision), 0) / cast(100 as double precision), 2) from rdb$database
...
Рейтинг: 0 / 0
Округление :|
    #39476140
WildSery
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
round(:value + 0.00001, 2)
...
Рейтинг: 0 / 0
Округление :|
    #39476159
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Luke221Проблема с фиксированной точкой другая - переполнение при умножении (там на самом деле
сложнее формула)

Значит на самом деле тебе не надо маяться дурью с плавающей точкой, а тщательно, согласно
бизнес-правилам, расставить приведение промежуточных результатов в этой формуле.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Округление :|
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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