Результат должен быть 806603.77, но почему я получаю 806603.8?Поплавок неправильный расчет
float a = 855000.00f;
float b = 48396.23f;
float res = a - b;
Console.WriteLine(res);
Console.ReadKey();
Результат должен быть 806603.77, но почему я получаю 806603.8?Поплавок неправильный расчет
float a = 855000.00f;
float b = 48396.23f;
float res = a - b;
Console.WriteLine(res);
Console.ReadKey();
Вы должны использовать decimal вместо потому float имеет 32-bit
с 7 цифр точность только поэтому результат отличается, с другой стороны decimal
имеет 128-bit
с 28-29 digit точность.
decimal a = 855000.00M;
decimal b = 48396.23M;
decimal res = a - b;
Console.WriteLine(res);
Console.ReadKey();
Выход: 806603.77
Потому что float
имеет ограниченную точность (32 бит). Используйте double
или decimal
если хотите более точный.
A float
(также называемый System.Single
) имеет точность, эквивалентную приблизительно seven десятичные числа. Вам нужны res
eight Значительные десятичные цифры. Поэтому следует ожидать, что в float
недостаточно точности.
Сложение:
Некоторые дополнительная информация: Около 806000 (806000), float
только имеет четыре бита влево для дробной части. Так res
ему придется выбирать между
806603 + 12/16 == 806603.75000000, and
806603 + 13/16 == 806603.81250000
Он выбирает первый, так как он ближе всего к идеальному результату. Но оба этих значения выводятся как "806603.8"
при вызове ToString()
(который вызывает Console.WriteLine(float)
). Показан максимум 7 значащих десятичных цифр с общим вызовом ToString
. Для того, чтобы показать, что два числа с плавающей точкой различны, даже если они печатают то же самое со стандартным форматированием, используйте строку формата "R"
, например
Console.WriteLine(res.ToString("R"));
Пожалуйста, обратите внимание, что только вслепую, используя Decimal не достаточно хорошо.
Читать ссылку размещенного Одедова: What Every Computer Scientist Should Know About Floating-Point Arithmetic
Только затем решение о соответствующем числовом типе использования.
Не попадайте в ловушку мышления о том, что просто использование десятичного числа даст вам точные результаты; это не всегда.
Рассмотрим следующий код: "! Yay"
Decimal d1 = 1;
Decimal d2 = 101;
Decimal d3 = d1/d2;
Decimal d4 = d3*d2; // d4 = (d1/d2) * d2 = d1
if (d4 == d1)
{
Console.WriteLine("Yay!");
}
else
{
Console.WriteLine("Urk!");
}
Если Десятичные вычисления были точны, что код должен печатать потому что d1 должен быть таким же, как d4, правильно?
Ну, это не так.
Также имейте в виду, что десятичные вычисления в тысячи раз медленнее, чем двойные вычисления.Они не всегда подходят для невалютных расчетов (например, вычисление смещений пикселей или физических вещей, таких как скорости или что-либо, что связано с трансцендентными числами и т. Д.).
Еще один забавный факт, заключающийся в том, что поскольку 'decimal.MaxValue'' '79228 ...', для чисел, чьи значащие цифры начинаются чем-то ниже этого, существует более высокая точность, чем число, значимые цифры которых выше. Чтобы понять, что я имею в виду, рассмотрим «800 м/3 м * 3 м» против «500 м/3 м * 3 м». Прежде всего отметим, что ни 800, ни 500 не равномерно смещаются на 3, поэтому у частного лица будет бесконечный хвост '666 ...', который 'System.Decimal' должен будет в конце концов завершить с' ... 667'. Тем не менее, поскольку 800 превысил предел '79228 ... ', а 500 находится под ним, точность отличается. –
Я говорю о пороге '79228 ...', где точность изменяется от 29 до 28 значащих цифр. –
Если вы хотите получить точный результат, воспользуйтесь десятичным – Sergio
[Что должен знать каждый компьютерный ученый о арифметике с плавающей точкой] (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – Oded
Float и Double подвержены проблемам округления. Используйте 'Десятичный', как @Sergio рекомендуется. Вы можете найти дополнительную информацию [здесь] (http://stackoverflow.com/questions/618535/what-is-the-difference-between-decimal-float-and-double-in-c) – npinti