C # Получение странных результатов для простых математических операций
1726 просмотра
4 ответа
Я заметил странное поведение при добавлении двух двойных чисел, иногда это работает правильно, а иногда нет!
Вот первый пример:
double num1 = 0.1 + 0.7; //Guess the result?
Легко - 0,8 !!! или нет?
Посмотрите на странный результат:
И угадайте, что, если оператор идет внутри блока else, и печатает num1
- и нет, он не печатает 0,799999999999993, он печатает 0,8.
Итак, я сделал еще один шаг вперед и попробовал этот код:
if (0.1 + 0.7 == 0.8) //Returns false ??
{
Console.WriteLine("Correct");
}
Хорошо, странно, но теперь я нашел правильный путь, он должен использовать f (float). Как я помню, в double много пробелов, поэтому он может содержать более высокие числа, возможно, в этом причина.
float num2 = 0.1f + 0.7f;
if (num2 == 0.8f) //Perfect - finally works !!!
{
Console.WriteLine("Correct");
}
else
{
Console.WriteLine(num2);
}
Но сейчас я пытаюсь это сделать - и опять возвращается ложь, почему?
if (0.1f + 0.7f == 0.8f) //Returns false :(
{
Console.WriteLine("Correct");
}
Результаты часов при его отладке:
Может кто-нибудь объяснить мне, что здесь не так? Это ошибки?
Заранее спасибо.
Автор: Misha Zaslavsky Источник Размещён: 12.11.2019 09:41Ответы (4)
6 плюса
Арифметика с плавающей точкой не является точной. Вы должны прочитать статью « Что должен знать каждый компьютерщик об арифметике с плавающей точкой» . Если вы хотите, чтобы ваши вычисления были точными в десятичном смысле, вы должны использовать decimal
тип, где 0.1m + 0.7m == 0.8m
есть true
. Следует отметить, что decimal
используются числа с плавающей запятой, такие же как float
и double
, за исключением того, что основание равно 10, а не 2. Поскольку работа с основанием 2 намного проще и оптимизирована, decimal
намного медленнее. Он также имеет свои собственные неточности, он точен только при работе с числами, которые могут быть представлены коротким числом десятичных цифр (например, 0.7
и 0.1
), что делает его пригодным для финансовых данных.
Еще одна полезная статья для понимания чисел с плавающей запятой - это формат Википедии с двойной точностью .
Автор: Tim S. Размещён: 26.10.2013 01:051 плюс
Вызовите метод Math.Round, чтобы убедиться, что оба значения имеют одинаковую точность. В следующем примере модифицируется предыдущий пример для использования этого подхода, чтобы два дробных значения были эквивалентны:
using System;
public class Example
{
public static void Main()
{
double value1 = .333333333333333;
double value2 = 1.0/3;
int precision = 7;
value1 = Math.Round(value1, precision);
value2 = Math.Round(value2, precision);
Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2, value1.Equals(value2));
}
}
// The example displays the following output:
// 0.3333333 = 0.3333333: True
Автор: Janycz
Размещён: 26.10.2013 01:09
1 плюс
Вот ответ: http://www.codeproject.com/Articles/383871/Demystify-Csharp-floating-point-equality-and-relat
Плавающие значения являются только приблизительными. Чтобы сравнить два значения с плавающей запятой, необходимо проверить разницу между ними. Разница не может быть больше чемfloat.Epsilon
Используйте это, чтобы сравнить эти значения:
bool AlmostEqualDoubles(double nVal1, double nVal2, int nPrecision = 6)
{
nPrecision = Math.Max(Math.Min(16, nPrecision), 0);
double nEpsilon = 1.0;
for (int i = 0; i < nPrecision; i++) nEpsilon *= 0.1;
return (nVal2 - nEpsilon) < nVal1 && nVal1 < (nVal2 + nEpsilon);
}
Автор: Damian Drygiel
Размещён: 26.10.2013 01:13
1 плюс
внутренне, double хранится в битах, в base-2. Все целые числа могут быть представлены точно в base-2, но когда дело доходит до дроби, это другое дело, все вместе.
Точно так же, как мы не можем точно представить результат 1/3 в нашей десятичной системе, в двоичной системе вы не можете представить все дроби. Поскольку десятичная дробь - это основание-10, легко представить x / 10 в десятичной системе счисления, но в base-2 это невозможно для некоторых x.
Поэтому всякий раз, когда вы используете удвоения, всегда помните о некоторых ошибках округления.
По этой причине двойные числа не должны использоваться всякий раз, когда требуются точные числа, как с денежными суммами.
Автор: oerkelens Размещён: 26.10.2013 01:08Вопросы из категории :
- c# Преобразовать десятичную в двойную?
- c# Как рассчитать чей-то возраст в C #?
- c# Как вы сортируете словарь по значению?
- c# В чем разница между int и Integer в Java и C #?
- c# Как создать новый экземпляр объекта из Типа
- c# Datatable против Dataset
- math Головоломка: Найти самый большой прямоугольник (проблема максимального прямоугольника)
- math Как округлить результат целочисленного деления?
- math Алгоритм нахождения наибольшего простого множителя числа
- math Рассчитать расстояние между двумя точками широты и долготы? (Формула Haversine)
- math Каков стандартный способ добавить N секунд для datetime.time в Python?
- math Наиболее эффективный способ реализации целочисленной степенной функции pow (int, int)
- console-application Когда следует использовать Environment.Exit для завершения консольного приложения?
- console-application Как отобразить элементы списка в окне консоли в C #
- console-application Доступ к SQL Server из консольного приложения
- console-application Как я могу получить путь к приложению в консольном приложении .NET?
- console-application Java gotoxy (x, y) для консольных приложений
- console-application Как консольное приложение C # Windows может определить, запущено ли оно в интерактивном режиме?