SQL Server — Странное круглое поведение при использовании переменной вместо простого значения

#sql #sql-server #floating-point #rounding

#sql #sql-server #с плавающей запятой #округление

Вопрос:

Я сталкиваюсь с этой странной проблемой в SQL Server при разделении числа с плавающей запятой, которое хранится в переменной, против, когда просто используется значение.

Случай следующий:

 DECLARE @FLOAT FLOAT = 6.80
print ROUND(@FLOAT / 2, 2, 0);  
print ROUND(@FLOAT / 2, 2, 1);  
 

Он печатает:

 3.4
3.39
 

Второй РАУНД, который усекает значение, дает неправильное значение. Оно должно быть 3.4, а не 3.39.

Но когда я использую значение без переменной, оно работает правильно:

 print ROUND(6.80 / 2, 2, 0);  
print ROUND(6.80 / 2, 2, 1);  
 

Он печатает:

 3.400000
3.400000
 

Кто-нибудь может помочь мне разобраться в этой проблеме?
Заранее спасибо.

Комментарии:

1. В этом нет ничего странного, вы используете a float для первого выражения и a decimal для второго, вы должны ожидать такого поведения. Базовые числа 2 и 10 действуют совершенно по-разному.

2. Спасибо за ваш быстрый комментарий. Извините, но я не думаю, что понял, что вы подразумеваете под «Базовыми числами 2 и 10 действуют совершенно по-разному», связанными с float .

3. Основание 2 или двоичные числа против основания 10 или десятичных чисел. Нецелые значения часто не могут быть точно сохранены с помощью первого. Например, прочитайте здесь .

Ответ №1:

Такое поведение ожидается. В первом выражении вы используете a float , а в последнем литерале decimal . Эти два типа данных очень разные. Первое значение имеет базовое значение 2, а второе — базовое значение 10.

6.80 невозможно сохранить точно с использованием базы 2, и поэтому его фактическое значение ближе к значению 6.79999999999999982236431605997495353221893310546875 . Как вы можете видеть, это немного меньше, чем, 6.8 и поэтому, когда вы делите это число на 2 , вы получаете число 3.40 , которое, вероятно 3.399999999999999911182158029987476766109466552734375 , немного меньше, чем.

В результате ROUND округляется число правильно, так как приведенное выше значение, округленное до 2 цифр 3.39 , нет 3.40 .

Для литерала 6.80 оно представлено точно, и so is 6.80 / 2 ( 3.40 ) поэтому, когда вы снова округляете это число до 2 знаков после запятой, вы все равно получаете 3.40