#sql-server #casting #floating-point #precision
#sql-server #Кастинг #с плавающей запятой #точность
Вопрос:
Я работаю с базой данных SQL Server, где мне нужно получить данные из столбца с типом real
в другой столбец в другой таблице с типом float
. Насколько я понимаю, real
это, по сути, просто float с меньшей точностью (24), по сравнению с float
которой по умолчанию имеет точность 53. Поэтому при приведении из real в float я ожидал бы получить большую точность или, по крайней мере, не потерять точность исходного значения. Однако при этом, похоже, теряется некоторая точность:
Почему это происходит и есть ли способ хотя бы сохранить точность исходных значений при этом?
Комментарии:
1. Реальный вопрос заключается в том, почему вы используете
float
иreal
нужны ли вам точные значения.2. Вы можете легко изменить тип данных столбца с помощью
ALTER
; хотя, если в столбцах естьCONSTRAINTS
иINDEX
, вам нужно сначалаDROP
их изменить, а затем воссоздать заново. Кроме того, если есть какие-либо объекты schemabound, ссылающиеся на них, их также необходимо будет удалить и воссоздать заново.3. Ваши исходные значения не являются точными — SSMS просто отображает их таким образом.
4. «Можно ли быстро выполнить эти изменения» технически вы могли бы использовать динамический оператор для
ALTER
них всех, но он, конечно, не будет учитывать какие-либо другие объекты, которые будут блокировать операцию. Что вы действительно хотели бы сделать, так это создать сценарий миграции в вашей среде разработки, чтобы у вас был большой пакет, который выполнял все изменения; и поскольку это разработчик, не имеет значения, что вы нарушаете. Что касается того, что произойдет во времяALTER
работы с таблицей, запросы, скорее всего, будут заблокированы до завершения выполнения инструкции DDL.5.
float
по-прежнему является неточным типом данных. Обаreal
иfloat
есть.
Ответ №1:
Я в замешательстве, почему SSMS округляет реальные значения при их отображении, но не делает то же самое для значений с плавающей запятой
Ближайшим числом с плавающей запятой одинарной точности ( real
) к 2.1 является что-то вроде 2.09999999. Поэтому имеет смысл отобразить его как 2.1.
Ближайшее число с плавающей запятой двойной точности ( float
) к 2.1 довольно далеко от 2.0999990000000, что примерно соответствует тому, что вы получаете при преобразовании 2.0999999 из real
float
в.
SSMS будет отображать значения с плавающей запятой ближе к 2.1 как 2.1, например
select cast(2.1 as float), cast(2.1 as float) - 0.000000000000001
отображается в виде
---------------------- ----------------------
2.1 2.1
Вот статья, в которой рассматриваются алгоритмы для этого преобразования и представлен новый: быстрая и точная печать чисел с плавающей запятой с помощью целых чисел
Ответ №2:
Так же, как дополнение к ответу Дэвида Брауна:
Похоже, прямое приведение вам не поможет. Вы можете получить «правильные» (лучшие) результаты, используя символьный тип, как следующий:
select cast(cast(Valuef as nvarchar(20)) as float)
В качестве примера select cast(cast(cast(2.1 as real) as nvarchar(20)) as float)
отображается просто 2.1
.