2012-06-20 4 views
6

Мне нужно преобразовать Float в Decimal (28,10) в SQL Server. Моя проблема заключается в том, что из-за характера float и способа преобразования, простое использование float может сделать его неправильным для моих пользователей.Преобразование Float в десятичный (SQL Server)

Например:

Float:    280712929.22 
Cast as Decimal:  280712929.2200000300 
What I think I want: 280712929.2200000000 

Я понимаю, немного о том, как флоат работ (что это примерный тип данных и т.д.), но по общему признанию, не достаточно, чтобы понять, почему это добавляет 300 в конце. Это просто мусор в качестве побочного эффекта преобразования, или это как-то более точное представление о том, что на самом деле хранит поплавок? Мне кажется, что он вытащил точность из воздуха.

В конечном счете, мне нужно, чтобы оно было точным, но и выглядело «правильно». Я думаю, мне нужно получить это нижнее число, так как тогда похоже, что я только что добавил конечные нули. Это возможно? Это хорошая или плохая идея, и почему? Другие предложения приветствуются.

Некоторые другие примеры:

Float:   364322379.5731 
Cast as Decimal: 364322379.5730999700 
What I want:  364322379.5731000000 

Float:   10482308902 
Cast as Decimal: 10482308901.9999640000 
What I want:  10482308902.0000000000 

Примечание стороны: новая таблица базы данных, которые я ставлю эти значения в читается моим пользователем. На самом деле им нужно только два десятичных знака прямо сейчас, но это может измениться в будущем, поэтому мы решили пойти с Decimal (28,10). Долгосрочная цель состоит в том, чтобы преобразовать столбцы с плавающей точкой, из которых я получаю свои данные от десятичных.

EDIT: Иногда поплавки, у которых у меня больше десятичных знаков, чем когда-либо понадобится, например: -0.628475064730907. В этой ситуации приведение к -0.6284750647 просто отлично. Мне в основном нужен мой результат, чтобы добавить нули в конец поплавка, пока у меня не будет 10 десятичных знаков.

+0

Может быть, я нашел ответ. http://stackoverflow.com/questions/34316871/how-can-the-following-result-of-casting-from-float-to-numeric-be-explained –

ответ

8

Вы должны бросить один раз в раунд, и один раз, чтобы добавить знаков после запятой назад (Есть и другие способы тоже, конечно же, с помощью STR, ROUND и т.д.):

DECLARE @c TABLE(x FLOAT); 

INSERT @c SELECT 280712929.22; 
INSERT @c SELECT 364322379.5731; 
INSERT @c SELECT 10482308902; 

SELECT x, 
    d = CONVERT(DECIMAL(28,10), x), 
    rd = CONVERT(DECIMAL(28,10), CONVERT(DECIMAL(28,4), x)) 
FROM @c; 

Результаты:

x    d      rd 
-------------- ---------------------- ---------------------- 
280712929.22 280712929.2200000300 280712929.2200000000 
364322379.5731 364322379.5730999700 364322379.5731000000 
10482308902  10482308902.0000000000 10482308902.0000000000 

Если вы хотите, чтобы он был точным и выглядел правильно, прекратите использовать FLOAT, что является приблизительным типом данных и не поддается логике для большинства людей за пределами строгого математического фона. Используйте DECIMAL с большим масштабом, чем вам нужно, и отформатируйте его до количества десятичных знаков, которые вам нужны сейчас (в ваших запросах, или создайте представление, или создайте вычисленный столбец). Если вы храните больше информации, чем вам нужно сейчас, вы всегда можете открыть ее позже. Вы также можете не предоставлять пользователям прямой доступ к вашей таблице.

+0

Число десятичных чисел может отличаться, по крайней мере, это что я думаю. –

+0

Это действительно помогает в определенной степени.Однако это означает, что я буду усекать цифры от поплавков, где на самом деле у меня на самом деле больше 4 десятичных знаков, то есть: 517822.18109027. Будет ли редактировать сообщение для уточнения. –

+2

Если вам нужно условно решить, сколько десятичных знаков будет отображаться в каждой строке, исходя из значения в этой строке, я думаю, что вы переходите на территорию синтаксического анализа/форматирования. Это, вероятно, лучше всего сделать на уровне презентации, а не в базе данных. –

1

Я не уверен, что это подпадает под кровосмешение, но недавно у меня была аналогичная проблема, поэтому я подумал, что могу опубликовать.

Это может быть уродливо, как грех, но, похоже, работает (изменено от ответа Аарона выше).

DECLARE @myTable TABLE(x FLOAT); 

INSERT INTO @myTable VALUES 
    (280712929.22), 
    (364322379.5731), 
    (10482308902), 
    (-0.628475064730907); 

SELECT x, 
     d = CONVERT(DECIMAL(28,10), x),     
     NewDec = CONVERT(DECIMAL(28,10),   
         CONVERT(DECIMAL(16,15), 
           LEFT(CONVERT(VARCHAR(50), x, 2),17)) 
         * POWER(CONVERT(DECIMAL(38,19),10), 
           RIGHT(CONVERT(varchar(50), x,2),4)))      
FROM @myTable; 

Результаты:

x     d      NewDec 
------------------ ---------------------- ---------------------- 
280712929.22  280712929.2200000300 280712929.2200000000 
364322379.5731  364322379.5731000300 364322379.5731000000 
10482308902   10482308902.0000000000 10482308902.0000000000 
-0.628475064730907 -0.6284750647   -0.6284750647 
Смежные вопросы