Двойная переменная, сохраняющая неправильное значение - PullRequest
0 голосов
/ 08 января 2010

Схожая проблема с Math.Atan2 или проблема экземпляра класса в C # а также добавить два двойных, учитывая неправильный результат

Это то, что простые строки:

public static String DegreeToRadianStr(Double degree)
    {
        Double piBy180 = (Math.PI / 180);

        Double Val = (piBy180 * degree);  // Here it is giving wrong value
    }

piBy180 * градус = -3.1415926535897931 но Val = -3.1415927410125732

альтернативный текст http://www.imagechicken.com/uploads/1262936639009840000.jpg Я действительно понятия не имею, что делать .. Пожалуйста, задайте несколько вопросов относительно этого, чтобы я мог указать, где это идет не так.

Удивительно, что piBy180 сохраняет правильное значение.

То же самое происходит и с другими функциями, но кое-как я манипулировал, чтобы получить правильные значения.

Я использую MS Visual Studio C # .net SP1.

Ответы [ 4 ]

3 голосов
/ 08 января 2010

Было бы полезно, если бы вы сказали нам значение degree, тогда мы могли бы попытаться воспроизвести проблему ...

Три вещи:

  • В арифметике с плавающей запятой следует ожидать определенного количества ошибок. Я не ожидал бы такого многого, но не ожидаю увидеть точное значение.
  • Строковые преобразования обычно не показывают точное значение. У меня есть файл - DoubleConverter.cs - с методом ToExactString, который может помочь в диагностике такого рода вещей.
  • Ваше приложение вообще использует DirectX? Это может изменить режим процессора для эффективного использования 32-битной арифметики, даже если в вашем коде есть двойные числа. Мне кажется, что это наиболее вероятная причина проблемы, но на самом деле это всего лишь предположение.

РЕДАКТИРОВАТЬ: Хорошо, звучит так, как я догадался, и DirectX, вероятно, является причиной. Вы можете передать CreateFlags.FpuPreserve в Device конструктор , чтобы избежать этого. По общему признанию, это снизит производительность DirectX, но это компромисс, который вы должны рассмотреть сами.

2 голосов
/ 08 января 2010

Это может быть просто проблема форматирования строки. Попробуйте добавить строку:

Debug.Assert(Val == (piBy180 * degree), "WTF?");

после назначения. Это не должно давать сбой, так как они оба являются двойными, и арифметические операции над ними должны давать одно и то же двоичное значение.

0 голосов
/ 08 января 2010

Это кажется невозможным.

Значение piBy180 * градуса вычисляется почти корректно, менее чем на 2 единицы в 17-й значащей цифре. Процессор должен выполнить умножение, чтобы сделать это, и он сделал это с двойной точностью, правильно, даже если кто-то попытался испортить точность, используя вызовы DirectX.

Значение Val неверно уже на 8-й значащей цифре. Val объявляется как double, и ему присваивается двойное значение, которое было вычислено микросекунду назад, без дальнейших вычислений.

Это сборка релиза? Интересно, мог ли C # не хранить последнее значение в Val, как это делает C ++. Что происходит в отладочной сборке?

0 голосов
/ 08 января 2010

Это может быть просто ошибка округления, но я не уверен.

Ознакомьтесь с этой статьей об арифметике с плавающей запятой. Это написано для фортрана, но все равно полезно. http://www.lahey.com/float.htm

...