В результате выполнения следующих методов (C# 2008):
Console.WriteLine(Math.Round(1.4999999999999999));
Console.WriteLine(Math.Round(1.49));
получил два разных результата — 2 и 1.
Первый, естественно, неверен.
Понятно почему так получается — из-за неточности представления числа
в бинарном виде.
Но, с другой стороны, как ни крути — это ошибка!
Или, всё-таки, фича?...
Здравствуйте, Vlad007, Вы писали:
V>В результате выполнения следующих методов (C# 2008): V> Console.WriteLine(Math.Round(1.4999999999999999)); V> Console.WriteLine(Math.Round(1.49)); V>получил два разных результата — 2 и 1. V>Первый, естественно, неверен. V>Понятно почему так получается — из-за неточности представления числа V>в бинарном виде. V>Но, с другой стороны, как ни крути — это ошибка! V>Или, всё-таки, фича?...
А вы заведите переменную типа double со значением 1.4999999999999999 и выведите ее на экран или отладчиком посмотрите.
Это не баг и не фича, это голая правда представления чисел с плавающей точкой.
Здравствуйте, Camarada, Вы писали:
C>А вы заведите переменную типа double со значением 1.4999999999999999 и выведите ее на экран или отладчиком посмотрите. C>Это не баг и не фича, это голая правда представления чисел с плавающей точкой.
Да я понимаю, что происходит за ширмой: строка "1.4999999999999999"
из моей программы при компиляции преобразуется в double,
получается значение чуть большее 1.5 и в результате —
совсем неверный ответ 2.
И ошибка заключается именно в том, что неявное преобразование к типу double
в данном случае недопустимо, оно приводит к существенной ошибке!
Здравствуйте, Vlad007, Вы писали:
V>И ошибка заключается именно в том, что неявное преобразование к типу double V>в данном случае недопустимо, оно приводит к существенной ошибке!
Тут нет неявного преобразования. Что значит строка к типу? Конкретно это число в double так и выглядит, его по другому не предствишь.
Здравствуйте, Vlad007, Вы писали:
V>Здравствуйте, Camarada, Вы писали:
C>>А вы заведите переменную типа double со значением 1.4999999999999999 и выведите ее на экран или отладчиком посмотрите. C>>Это не баг и не фича, это голая правда представления чисел с плавающей точкой.
V>Да я понимаю, что происходит за ширмой: строка "1.4999999999999999" V>из моей программы при компиляции преобразуется в double, V>получается значение чуть большее 1.5 и в результате — V>совсем неверный ответ 2. V>И ошибка заключается именно в том, что неявное преобразование к типу double V>в данном случае недопустимо, оно приводит к существенной ошибке!
Странное у вас представление. По умолчанию число в формате x.x — System.Double.
Как вы представляете компилятор должен догадаться, что вы хотите передать в метод. Он же должен сохранить это число на стеке и прочее.
Для точных расчетов в .NET есть тип Decimal (забыл написать), почитайте статью об этом типе в MSDN.
Здравствуйте, Camarada, Вы писали:
C>Для точных расчетов в .NET есть тип Decimal (забыл написать), почитайте статью об этом типе в MSDN.
Decimal не спасает от проблем с многократным округлением:
using System;
class A
{
static void Main()
{
var x = 1E-28M;
Console.WriteLine(0 == x * 0.5M); // True
Console.WriteLine(0 == x * 0.50000000000000000000000000005M); // True
Console.WriteLine(0 == x * 0.50000000000000000000000000005000000000000000000001M); // False
}
}
Здравствуйте, nikov, Вы писали:
N>Здравствуйте, Camarada, Вы писали:
C>>Для точных расчетов в .NET есть тип Decimal (забыл написать), почитайте статью об этом типе в MSDN.
N>Decimal не спасает от проблем с многократным округлением: