Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 округление данных  [new]
gas
Guest
Здравствуйте !
Обнаружены ошибки округления.
Например, запрос select round(36.467, 2)
возвращает 36.470, - как и положено.
Однако, при выполнении

update waylistDrive set fuelNorm =
mf.baseNorm * ac.coeff *(ld.runNorm / 100)
from ...
where ...

значение fuelNorm устанавливается не в 36.47 а в 36.46

Поле fuelnorm is type numeric(5, 2)
Я изменил его формат на numeric(6, 3), выполнил расчёт, получил 36.467,
затем выполнил fuelNorm = round(fuelNorm, 2) и опять получил 36.46.
Как с этим бороться ? Не писать же собственную процедуру округления ?
24 сен 04, 06:11    [984052]     Ответить | Цитировать Сообщить модератору
 Re: округление данных  [new]
sti
Member

Откуда:
Сообщений: 769
Если вместо того, чтобы описывать словами что ты делал, ты напишешь как это было на самом деле, то шансов разобраться будет гораздо больше.
24 сен 04, 06:50    [984066]     Ответить | Цитировать Сообщить модератору
 Re: округление данных  [new]
gas
Guest
я выполнил запрос:
update waylistDrive set fuelNorm =
mf.baseNorm * ac.coeff *(ld.runNorm / 100)
from ...
where ...

затем стал проверять расчёты, и в некоторых строках обнаружил отличие от ожидаемого значения: 36.46 вместо 36.47. После этого на отладочном сервере изменил формат данных и вновь запустил расчёт, - как написал в первом сообщении. Непонятно, почему на табличных данных round(fuelNorm, 2) для значения fuelNorm=36.467 возвращает 36.46, а на переменной памяти 36.47 ?
24 сен 04, 07:49    [984103]     Ответить | Цитировать Сообщить модератору
 Re: округление данных  [new]
MVM
Member

Откуда:
Сообщений: 271
fuelNorm =
round(mf.baseNorm * ac.coeff *(convert(float,ld.runNorm) / 100),2)
24 сен 04, 08:01    [984112]     Ответить | Цитировать Сообщить модератору
 Re: округление данных  [new]
Алексей2003.
Guest
update set (mf.baseNorm * ac.coeff *ld.runNorm) / 100
 from
  where
24 сен 04, 08:10    [984119]     Ответить | Цитировать Сообщить модератору
 Re: округление данных  [new]
MVM
Member

Откуда:
Сообщений: 271
BOL
Converting from decimal or numeric to float or real can result in some loss of 
precision. Converting from int, smallint, tinyint, float, real, money, or smallmoney to 
either decimal or numeric can result in overflow.

By default, SQL Server uses rounding when converting a number to a decimal or 
numeric value with a lower precision and scale. However, if the SET ARITHABORT 
option is ON, SQL Server raises an error when overflow occurs. Loss of only 
precision and scale is not sufficient to raise an error.

24 сен 04, 08:12    [984120]     Ответить | Цитировать Сообщить модератору
 Re: округление данных  [new]
sti
Member

Откуда:
Сообщений: 769
автор
затем стал проверять расчёты ...


Вот и напиши как ты их проверял. А заодно и типы полей, которые участвуют в формуле. И неплохо бы еще и их значения.
24 сен 04, 08:15    [984126]     Ответить | Цитировать Сообщить модератору
 Re: округление данных  [new]
gas
Guest
MVM !
сейчас проверю.

2 sti
mf.baseNorm is decimal(4, 2)
ac.coeff is numeric(5, 3)
ld.runNorm is numeric(5, 2)

а проверял данные я по "старой" БД (dbf & Clipper)
24 сен 04, 09:33    [984225]     Ответить | Цитировать Сообщить модератору
 Re: округление данных  [new]
sti
Member

Откуда:
Сообщений: 769
я согласен с MVM - надо сначала произвести все действия, а потом округлять.

Но хотелось бы увидеть код, подтверждающий
автор
Непонятно, почему на табличных данных round(fuelNorm, 2) для значения fuelNorm=36.467 возвращает 36.46, а на переменной памяти 36.47 ?
24 сен 04, 10:39    [984468]     Ответить | Цитировать Сообщить модератору
 Re: округление данных  [new]
gas
Guest
Пробовал разные способы округления, даже вместо "сто" использовал @hundred numeric(6, 2), - не помогло.
а для данной записи значения таковы:

mf.baseNorm is decimal(4, 2)
ac.coeff is numeric(5, 3)
ld.runNorm is numeric(5, 2)

mf.baseNorm = 16.00
ac.coeff = 1.600
ld.runNorm = 207.20

подтверждающий код - это
uddate waylistDrive set fuelNorm = round(fuelNorm, 2)
from waylistDrive
where ...

где waylistDrive.fuelNorm type numeric(6, 3)
и значение поля 36.467
24 сен 04, 11:17    [984641]     Ответить | Цитировать Сообщить модератору
 Re: округление данных  [new]
Алексей2003.
Guest
учимся умножать?
select 16.00*1.600*(207.20/100)
есть 53.04320000000
24 сен 04, 11:31    [984726]     Ответить | Цитировать Сообщить модератору
 Re: округление данных  [new]
gas
Guest
Ну, я и баран !

ac.coeff = - это сумма неких коэффициентов и равен не 1.6, а 1.100
(1 + 10% = 1.100)
т.е. так:
mf.baseNorm = 16.00
ac.coeff = 1.100
ld.runNorm = 207.20

Создал таблицу с одним полем, в ней round работает верно.
24 сен 04, 13:24    [985254]     Ответить | Цитировать Сообщить модератору
 Re: округление данных  [new]
Алексей2003.
Guest
select round(16.00*1.100*(207.20/100), 2)
выдает именно то что вам надо.
скорее всего вам нужно гдето поменять алгоритм заполнения... врет именно он.
24 сен 04, 13:29    [985275]     Ответить | Цитировать Сообщить модератору
 Re: округление данных  [new]
Crimean
Member

Откуда:
Сообщений: 13148
Исчо раз предложу свой рецепт.

round( 1. * наше выражение , 2 )

Работает атлична уже много лет. Простая спекуляция на неявном преобразовании типов.

P.S.Мы с numeric и float не работаем, только money + int, так что повнимательнее, но работать все равно должно :)
24 сен 04, 14:25    [985499]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить