Я столкнулся с проблемой точности при расчете рациона между двумя единицами измерения.Linq to SQL округление десятичного числа после деления
Ratio хранятся в базе данных SQL Server в UnitOfMeasureTable как: NumberOfDefaultUnits десятичного (28,18)
В моем примере LINQPad У меня есть класс, чтобы продемонстрировать режим, что происходит не так.
private class Test
{
public decimal saleUom { get; set; }
public decimal piUom { get; set; }
public decimal RatioRight { get; set; }
public decimal RatioWrong { get; set; }
public decimal CalcledAlsoRight { get { return saleUom/piUom; } }
}
недействительным Main() {
var xx = from uom in UnitsOfMeasures.Where(d=> d.Id == 9)
let buyUom = uom.NumberOfDefaultUnits
let sellUom = UnitsOfMeasures.First(d=> d.Id == 13).NumberOfDefaultUnits
select new Test
{
saleUom = sellUom,
piUom = buyUom,
RatioRight = sellUom/(buyUom * 1m),
RatioWrong = sellUom/buyUom,
};
xx.First().Dump();
}
Результаты:
saleUom 453.592370000000000000
piUom 1000000.000000000000000000
RatioRight 0.000453592370000000000
RatioWrong 0.0004535923
CalcledAlsoRight 0.00045359237
потребовалось некоторое время, чтобы выяснить, нужно умножить делитель на 1 м, чтобы получить правильный результат. Он становится еще более странным, если вы умножаете sellUom на 1 м. Тогда результат:
RatioRight = (sellUom * 1m)/(buyUom)
RatioRight 0.000453
Я предполагаю, что это что-то делать с тем, как SQL Server, магазинами десятичной (28,18) и как Linq преобразует команду деления.
Update: Все значения являются десятичными
Update 2: Похоже, это целиком и полностью SQL округления вещи. Удаление .Net из уравнения
select top 1 uom.NumberOfDefaultUnits
from UnitOfMeasures uom
where uom.Id = 13
select (select top 1 uom.NumberOfDefaultUnits
from UnitOfMeasures uom
where uom.Id = 13)
/
(select top 1 uom.NumberOfDefaultUnits
from UnitOfMeasures uom
where uom.Id = 9)
Первый запрос возвращает: 453,592370000000000000
Второе: 0,0004535923
Похож, что 'buyUom' является' integer'. Я готов поспорить, что это имеет какое-то отношение к этому. Если вы умножаете его на '1m', он преобразуется в' decimal'. Я не уверен в этом случае, каков эффект деления десятичной дроби с целым числом. – HoneyBadger
@HoneyBadger Nope, buyUom имеет дефолиал. он поступает прямо из столбца Decimal (28,18) в таблице UnitOfMeasure. Добавить скриншот –
Вы можете посмотреть, что такое ценность 'buyUom'? Это может отличаться от значения при присвоении 'piUom' (по отношению к значимым цифрам). – HoneyBadger