Запуск быстрого эксперимента, связанного с Является ли двойное умножение разбитым в .NET? и прочитав пару статей о форматировании строк в С#, я подумал, что это:
{
double i = 10 * 0.69;
Console.WriteLine(i);
Console.WriteLine(String.Format(" {0:F20}", i));
Console.WriteLine(String.Format("+ {0:F20}", 6.9 - i));
Console.WriteLine(String.Format("= {0:F20}", 6.9));
}
Был бы эквивалент С# этого кода C:
{
double i = 10 * 0.69;
printf ( "%f\n", i );
printf ( " %.20f\n", i );
printf ( "+ %.20f\n", 6.9 - i );
printf ( "= %.20f\n", 6.9 );
}
Однако С# выдает результат:
6.9
6.90000000000000000000
+ 0.00000000000000088818
= 6.90000000000000000000
несмотря на то, что я показываю значение, равное значению 6.89999999999999946709 (а не 6.9) в отладчике.
по сравнению с C, который показывает точность, запрошенную в формате:
6.900000
6.89999999999999946709
+ 0.00000000000000088818
= 6.90000000000000035527
Что происходит?
(Microsoft.NET Framework версии 3.51 с пакетом обновления 1 (SP1)/Visual Studio С# 2008 Express Edition)
У меня есть фон в численных вычислениях и опыт реализации интервальной арифметики - метод оценки ошибок из-за пределов точности в сложных числовых системах - на разных платформах. Чтобы получить награду, не пытайтесь объяснить точность хранения - в этом случае это разница в одном ULP 64-битного двойника.
Чтобы получить щедрость, я хочу знать, как (или нет).Net может форматировать двойную требуемую точность как видимую в коде C.