Почему десятичные ведут себя по-разному? - PullRequest
0 голосов
/ 12 апреля 2010

Я делаю это небольшое упражнение.

declare @No decimal(38,5);
set @No=12345678910111213.14151;

select @No*1000/1000,@No/1000*1000,@No;

Результаты:

12345678910111213.141510    
12345678910111213.141000    
12345678910111213.14151

Почему результаты первых 2 выборов отличаются, когда математически они должны быть одинаковыми?

Ответы [ 7 ]

2 голосов
/ 12 апреля 2010

Алгебра не собирается преобразовывать 1000/1000 в 1. Она будет фактически следовать порядку операций и выполнять каждый шаг.

@No*1000/1000
 yields:  @No*1000  =  12345678910111213141.51000
          then /1000=  12345678910111213.141510

и

    @No/1000*1000
yields:  @No/1000  = 12345678910111.213141
         then *1000= 12345678910111213.141000

при первом делении вы теряете десятичные цифры.

2 голосов
/ 12 апреля 2010

потому что когда вы делите первым, вы получаете:

12345678910111.21314151

тогда после точки остается только шесть десятичных цифр:

12345678910111.213141

затем *1000* 1007 *

12345678910111213.141
2 голосов
/ 12 апреля 2010

из-за округления второй sql сначала делится на 1000, что составляет 12345678910111.21314151, но ваше десятичное число составляет всего 38,5, поэтому вы теряете три последних десятичных знака.

1 голос
/ 12 апреля 2010

Вероятно, потому, что вы сначала теряете часть подразделения по созданию данных Обратите внимание, что @No имеет 5-точечную десятичную точность, поэтому, когда вы делите это число на 1000, вам внезапно нужны 8 цифр для десятичной части:

123.12345 / 1000 = 0.12312345

Таким образом, значение должно быть округлено (0.12312), а затем это значение умножается на 1000 -> 123.12 (вы теряете 0.00345.

Я думаю, поэтому результат такой, какой он есть ...

1 голос
/ 12 апреля 2010

потому что тип-посредник совпадает с типом аргумента - в данном случае десятичный (38,5). поэтому сначала деление дает вам потерю точности, что отражено в усеченном ответе. умножение на 1000 вначале не приводит к потере точности, поскольку это не приводит к перегрузке 38 цифр.

0 голосов
/ 12 апреля 2010

Вы можете обойти проблему, используя CONVERT или CAST для первого значения в вашем выражении, чтобы увеличить количество десятичных разрядов и избежать потери точности.

DECLARE @num decimal(38,5)
SET @num = 12345678910111213.14151

SELECT CAST(@num AS decimal(38,8)) / 1000 * 1000
0 голосов
/ 12 апреля 2010

Первый делает @No*1000, затем делит его на 1000. Промежуточные значения всегда могут представлять все десятичные знаки. Второе выражение сначала делит на 1000, что отбрасывает последние два десятичных знака перед умножением обратно на исходное значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...