Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
denmat Member Откуда: Сообщений: 3 |
SQL2008r2declare @m float set @m=150.20 select @m as a, --150.2 CAST((@m * 100) as int) as b, --15019 CAST((@m * 1000) as int) as c --150200 Как с этим бороться? И почему именно при умножении на 100 вывалилась проблема? Ясно, что лучше вообще избегать float, но у нас оно много где используется. |
24 июл 12, 14:13 [12908390] Ответить | Цитировать Сообщить модератору |
SomewhereSomehow Member Откуда: Moscow Сообщений: 2480 Блог |
denmat, float не точный тип, почему конкретно именно 150.2 на 100 не может правильно умножить и преобразовать к инту сказать трудно, 150.1 или 150.3 нормально проходят. В этом примере, можно привести сначала флоат к децималу, а потом уже с ним выполнять действия. |
24 июл 12, 14:27 [12908489] Ответить | Цитировать Сообщить модератору |
Сид Member Откуда: Москва Сообщений: 305 |
denmat, потому что float - это весьма неточный тип данных, а приведение к int отсекает всю нецелую часть (а не округляет). Т.е. реально в переменной оказалось что-то типа 150.199999999 (цифру взял от балды). Если так уж важен float, вместо int можно использовать decimal: declare @m float set @m=150.20 select @m as a, --150.2 CAST((@m * 100) as dec(29,0)) as b, --15020 CAST((@m * 1000) as dec(29,0)) as c --150200 Но лучше изначально использовать decimal, особенно если в дальнейшем будет масса разных вычислений. |
24 июл 12, 14:31 [12908510] Ответить | Цитировать Сообщить модератору |
Сид Member Откуда: Москва Сообщений: 305 |
upd: пример с cast( as dec(29,10)) работает именно для 150.2, но не факт, что будет работать для другого числа. Избавьтесь от float и не насилуйте мозг)) |
24 июл 12, 14:34 [12908537] Ответить | Цитировать Сообщить модератору |
denmat Member Откуда: Сообщений: 3 |
Избавиться дело не хитрое. Вот понять бы суть проблемы. |
24 июл 12, 14:48 [12908665] Ответить | Цитировать Сообщить модератору |
Glory Member Откуда: Сообщений: 104760 |
Проблема с понимаем арифметики чисел с плавующей запятой |
||
24 июл 12, 14:54 [12908699] Ответить | Цитировать Сообщить модератору |
Shakill Member Откуда: мск Сообщений: 1882 |
потому что fioat - неточный тип, вам же сказали declare @m float = 150.2 select cast(@m as decimal(20, 17)) |
||
24 июл 12, 14:57 [12908733] Ответить | Цитировать Сообщить модератору |
мимо
Guest |
denmat, В типе флоат (как впрочем и в децимале и иных ), в отличии от инта, хранится не само число, а некая совокупность аргументов для определенной функции, согласно которой и вычисляется искомое. На пальцах |
24 июл 12, 15:53 [12909181] Ответить | Цитировать Сообщить модератору |
Deff Member Откуда: Пермь Сообщений: 18326 |
declare @m float set @m=150.20 select @m as a, --150.2 CAST((@m * 100) as int) as b, --15019 CAST((@m * 1000) as int) as c select @m as a, --150.2 @m * 100 as b, --15020 @m * 1000 as c --150200 Пофиг что флоат не точный тип. Это все равно явный косяк при конвертации. |
24 июл 12, 16:22 [12909434] Ответить | Цитировать Сообщить модератору |
Deff Member Откуда: Пермь Сообщений: 18326 |
Вот так кстати работает. И всегда будет работатьdeclare @m float set @m=150.20 select @m as a, --150.2 CAST(round((@m * 100),0) as int) as b --15020 |
24 июл 12, 16:24 [12909445] Ответить | Цитировать Сообщить модератору |
denmat Member Откуда: Сообщений: 3 |
Я сделал cast(@m numeric(18,2)) |
24 июл 12, 16:26 [12909457] Ответить | Цитировать Сообщить модератору |
Deff Member Откуда: Пермь Сообщений: 18326 |
Вот что нашел в БОЛе.
Так что это задокументированный косяк. |
||
24 июл 12, 16:28 [12909468] Ответить | Цитировать Сообщить модератору |
Deff Member Откуда: Пермь Сообщений: 18326 |
Надо именно делать round до нужного количества. round гарантированно округлит по правилам. |
||
24 июл 12, 16:29 [12909480] Ответить | Цитировать Сообщить модератору |
Glory Member Откуда: Сообщений: 104760 |
Косяк - это для тех, кто не знает принципов работы с такими числами. А для остальных - это нормально. |
||
24 июл 12, 16:34 [12909507] Ответить | Цитировать Сообщить модератору |
Deff Member Откуда: Пермь Сообщений: 18326 |
От того что я понимаю как устроен флоат, мне удобней работать не становится. Это язык высокого уровня. При усечении дробной части вполне логично делать округление, а не обрезание. |
||||
24 июл 12, 16:47 [12909618] Ответить | Цитировать Сообщить модератору |
Glory Member Откуда: Сообщений: 104760 |
Это не косяк. Есть разные стандарты работы с числами с плавающей точкой.
Удобнее кому ? |
||||
24 июл 12, 16:51 [12909659] Ответить | Цитировать Сообщить модератору |
мимо
Guest |
declare @float1 as float = 0.3 declare @float2 as float = 3 declare @float3 as float = 2 set @float1 = (@float1/ @float2)*@float3 +255 set @float1 = (@float1-255)*@float2/@float3 select @float1 declare @d1 as decimal(18,8) = 0.3 declare @d2 as decimal(18,8) = 3 declare @d3 as decimal(18,8) = 2 set @d1 = (@d1/@d2)*@d3 +255 set @d1 = (@d1-255)*@d2/@d3 select @d1 |
24 июл 12, 16:51 [12909667] Ответить | Цитировать Сообщить модератору |
Deff Member Откуда: Пермь Сообщений: 18326 |
Сделано ради быстродействия? - Сомневаюсь. |
||||
24 июл 12, 17:00 [12909752] Ответить | Цитировать Сообщить модератору |
Massa52 Member Откуда: Сообщений: 382 |
Deff, float используется для инженерных расчетов - там целые числа почти не используются. Ни один физик не оперирует целыми - у них там все приблизительно с точностью до ... И обычно операции с плавающей запятой выполняет специализированная часть проца. И если тебе нужно челое число - будь добр - округли с нужной точностью и переходи в область целых чисел. Не стоит мешать целое с плавающим - таково правило - если не хочешь проблем. |
24 июл 12, 17:13 [12909864] Ответить | Цитировать Сообщить модератору |
iap Member Откуда: Москва Сообщений: 47045 |
|
||
24 июл 12, 17:17 [12909895] Ответить | Цитировать Сообщить модератору |
Lepsik Member Откуда: glubinka Сообщений: 4256 |
#define FLT_EPSILON 1.192092896e-07F /* smallest such that 1.0+FLT_EPSILON != 1.0 */ |
||
25 июл 12, 00:12 [12911217] Ответить | Цитировать Сообщить модератору |
Glory Member Откуда: Сообщений: 104760 |
Вы почему думаете, что разрядность операций и промежуточных результатов вещественных чисел у SQL Server бесконечна. А также думаете, что неявное преобразование одних типов в другие делается по вашим правилам. Вот умножьте массу солнца на массу электрона, используя только разрешенную в MSSQL точность для веществеееых чисел. |
||
25 июл 12, 13:04 [12913450] Ответить | Цитировать Сообщить модератору |
Все форумы / Microsoft SQL Server | ![]() |