SQL-сервер 2005 числовая потеря точности

Для целых:

var x=12345678;
x=x.toString();
var lastThree = x.substring(x.length-3);
var otherNumbers = x.substring(0,x.length-3);
if(otherNumbers != '')
    lastThree = ',' + lastThree;
var res = otherNumbers.replace(/\B(?=(\d{2})+(?!\d))/g, ",") + lastThree;

alert(res);

Live Demo

Для float:

var x=12345652457.557;
x=x.toString();
var afterPoint = '';
if(x.indexOf('.') > 0)
   afterPoint = x.substring(x.indexOf('.'),x.length);
x = Math.floor(x);
x=x.toString();
var lastThree = x.substring(x.length-3);
var otherNumbers = x.substring(0,x.length-3);
if(otherNumbers != '')
    lastThree = ',' + lastThree;
var res = otherNumbers.replace(/\B(?=(\d{2})+(?!\d))/g, ",") + lastThree + afterPoint;

alert(res);

Live Demo

5
задан MrValdez 4 October 2008 в 00:37
поделиться

2 ответа

Так же, как добавление типа плавающего неточно, умножение десятичных типов может быть неточным (или вызвать погрешность) при превышении точности. Посмотрите Преобразование типа данных и десятичный и числовой.

Так как Вы умножились NUMERIC(24,8) и NUMERIC(24,8), и SQL Server только проверит тип не содержание, это, вероятно, попытается сохранить потенциальные 16 недесятичных цифр (24 - 8), когда это не сможет сохранить все 48 цифр точности (макс. 38). Объедините два из них, Вы получаете 32 недесятичных цифры, который оставляет Вас только с 6 десятичными цифрами (38 - 32).

Таким образом исходный запрос

SELECT A, B, C, A + B * C
FROM ( SELECT CAST(0.12345678 AS NUMERIC(24,8)) AS A,
  CAST(0 AS NUMERIC(24,8)) AS B,
  CAST(500 AS NUMERIC(24,8)) AS C ) T

уменьшает до

SELECT A, B, C, A + D
FROM ( SELECT CAST(0.12345678 AS NUMERIC(24,8)) AS A,
  CAST(0 AS NUMERIC(24,8)) AS B,
  CAST(500 AS NUMERIC(24,8)) AS C,
  CAST(0 AS NUMERIC(38,6)) AS D ) T

Снова, между NUMERIC(24,8) и NUMERIC(38,6), SQL Server попытается сохранить потенциальные 32 цифры недесятичных чисел, таким образом, A + D уменьшает до

SELECT CAST(0.12345678 AS NUMERIC(38,6))

который дает Вам 0.123457 после округления.

7
ответ дан 14 December 2019 в 09:05
поделиться

После логики, на которую указывает eed3si9n и что Вы сказали в своем вопросе, что кажется, что лучший подход, когда выполнение операций математики должно извлечь их в функцию и дополнительно указывать точность после каждой операции,

Это этот случай функция могло посмотреть что-то как:

create function dbo.myMath(@a as numeric(24,8), @b as numeric(24,8), @c as numeric(24,8))
returns  numeric(24,8)
as
begin 
    declare @d as numeric(24,8)
    set @d = @b* @c
    return @a + @d
end
0
ответ дан 14 December 2019 в 09:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: