Неверные значения для двойного расчета
Я делаю простой расчет в VB.Net, следующий код.
Dim total As String = "192.04"
Dim paid As String = "200"
Dim change As String = "7.96"
'//This prints -7.99360577730113E-15 (Incorrect)
MsgBox((CDbl(total) - CDbl(paid)) + CDbl(change))
Ответ, который я ожидаю из этого расчета, равен 0, но я получаю -7.99360577730113E-15. Я не знаю точную причину этого, я не мог понять причину, объясненную на MSDN. Любое разъяснение будет очень полезно.
И я сделал Math.Round до 2 десятичных знаков, и проблема была решена, поэтому мне нужно использовать Math.Round везде, где я делаю вычисления с десятичными знаками?
2 ответа
Это из-за того, как double
(или числа с плавающей запятой вообще) представлены в памяти. Вы должны использовать decimal
для финансовых расчетов вместо double
:
double total = 192.04;
double paid = 200;
double change = 7.96;
double result = (total - paid) + change; // -7.99360577730113E-15
decimal total = 192.04m;
decimal paid = 200m;
decimal change = 7.96m;
decimal result = (total - paid) + change; // 0.00
Я знаю, что это C#, но вы все равно должны увидеть разницу.
Ты можешь использовать Decimal.Parse
чтобы получить decimal
от string
:
Dim total As String = "192.04"
Dim paid As String = "200"
Dim change As String = "7.96"
MsgBox((Decimal.Parse(total) - Decimal.Parse(paid)) + Decimal.Parse(change))
Эта ошибка точности связана с тем, как числа с плавающей запятой работают в компьютерах (более конкретно, стандарт IEEE, см. WikiPedia). Короче говоря, числа с плавающей запятой хранятся как "двоичные числа с десятичными точками", а затем увеличиваются до некоторой степени 2. Поэтому они не могут хранить точные десятичные цифры. Эта проблема является общей для всех языков программирования, а не только для.NET.
Чтобы преодолеть эту проблему, Decimal
Тип используется при расчете платежей, которые требуют точности базы 10. За исключением.NET, почти все современные среды программирования также предоставляют этот тип переменной.