Проблемы с точностью в Visual Studio 2010

У меня есть приложение, написанное на Microsoft Visual C++ 6.0. Теперь я переписал приложение в Visual Studio 2010 с помощью C#, но результаты не совпадают из-за проблем с точностью. Одной из таких проблем точности является следующая.

float a = 1.0f;

float b = 3.0f;

float c = a / b;

Это код C# при запуске в Visual Studio 2010 дает значение c = 0.333333343

Но тот же код, удаляющий f после значения в определении значения, при выполнении на Visual C++ 6.0 дает значение c = 0.333333.

Может ли кто-нибудь разобраться и объяснить, как получить одинаковое значение для c в Visual Studio, а также в Visual C++ 6.0 ??


На самом деле значения берутся из окна просмотра. Я узнал, что разные версии Visual Studio могут отличаться в представлении формата с плавающей запятой. Следовательно, значения в часах могут быть бесполезны. По этой причине я напечатал значения в обеих версиях Visual Studio, и результаты следующие. с Visual Studio 6.0 с использованием языка Visual C++ это 0,333333 (шесть троек)

но с Visual Studio 10 с использованием языка С# это 0,3333333 (семь троек)

Так может ли кто-нибудь помочь мне заставить мою программу на С# давать тот же результат, что и визуальный С++??? (т.е. как я могу выполнять плавающие операции для получения одинаковых результатов в обеих версиях???)


person Mahesh    schedule 15.12.2011    source источник
comment
Как вы смотрите на ценности? Я почти уверен, что внутреннее представление такое же (если я не ошибаюсь и С# использует double за кулисами), но методы отображения числа пользователю различаются, поэтому вы можете просто смотреть на разные значения по умолчанию для отображения.   -  person Mr Lister    schedule 15.12.2011
comment
@MrLister спецификация C# 4.0 говорит в разделе 4.1.6, что двоичная операция над числами с плавающей запятой выполняется с использованием минимум float диапазона и точности (выделение добавлено). Таким образом, закулисная точность определяется реализацией. .NET Framework вполне может использовать двойников за кулисами.   -  person phoog    schedule 28.12.2011


Ответы (4)


Учитывая, что точное значение равно 0,3, ни одно из них не является «правильным». как они работают. (Дополнительную информацию см. в моей статье о двоичных числах с плавающей запятой в .NET.)

Возможно вам вообще не следует использовать двоичные числа с плавающей запятой (например, если ваши значения представляют точные, искусственные суммы, такие как деньги). В качестве альтернативы, возможно, вам следует выполнять сравнения равенства только с определенным допуском.

также возможно, что C# и C создают один и тот же битовый шаблон, но вы видите разные результаты из-за того, как эти значения форматируются. Опять же, я бы не стал использовать текстовое представление чисел для сравнения.

person Jon Skeet    schedule 15.12.2011
comment
Я напечатал оба значения: визуальный С++ дает 0,333333 (шесть 3), а С# дает 0,3333333 (семь троек). Это означает, что в этом есть ошибка. Как сделать так, чтобы Visual C++ 6.0 и Visual Studio 10 с C# давали одинаковые результаты? - person Mahesh; 28.12.2011
comment
@Mahesh: Нет, это не значит, что есть ошибка. Я подозреваю, что в каждом случае это связано с форматированием текста. - person Jon Skeet; 28.12.2011

C# просто отображает меньше знаков после запятой. 0.333333343, округленное до шести значащих цифр, равно 0.333333. Базовое значение c такое же.

Конечно, если вам нужна большая точность, вы всегда можете использовать double переменных.

person TonyK    schedule 15.12.2011

Плавающая точка C# может обрабатываться типами float и double. Тип float имеет точность 7 цифр, а тип double 16.

Я считаю, что стандартная точность С++ составляет около 16 цифр (в среднем 15,9!).

В любом случае ни одно из представлений не является арифметически правильным, поскольку 1/3 повторяется 0,333.

Я думаю, что это просто представление значения, которое вы видите (имейте в виду, что отладчик преобразует значение в строку для отображения. Если вы проверите ячейки памяти для каждого из них, вы, вероятно, обнаружите, что значения одинаковы.

person ChrisBD    schedule 15.12.2011

Быстрая проверка показывает, что да, цифры точно такие же. Таким образом, ответ на ваш вопрос таков: если вам нужен один и тот же вывод, все, что вам нужно сделать, это убедиться, что методы отображения совместимы.
Например, printf("%9.7f", result) в C и string.Format("{0:0.0000000}", result) в C#. Это все.

person Mr Lister    schedule 15.12.2011