2013-08-06 6 views
1

После дальнейших исследований, все это сводится к следующему:C# двойное значение отображается как .9999998?

(decimal)((object)my_4_decimal_place_double_value_20.9032) 

после заливки в два раза, то становится 20,903199999999998


У меня есть двойное значение, которое округленное до всего 4 десятичных точек с помощью Math.Round(...) значение равно 20.9032

В моей среде dev она отображается как есть.

Но в выпущенном среде, он отображается как 20.903199999999998

Там не было никакой операции после Math.Round(...) но стоимость была скопирована вокруг и назначена.

Как это может произойти?

Обновления: Данные не загружаются из базы данных.

возвращенное значение от Math.Round() относится к оригинальной двойной вариабеле.

Релиз и dev - это та же архитектура, если эта информация помогает.

+0

Вы извлекаете DB формы значений и назначаете управление для отображения? – SeeSharp

+0

Math.Round возвращает число, устанавливаете ли вы это значение? – Sayse

+0

Разве dev и релиз env той же архитектуры? –

ответ

2

В соответствии со спецификацией CLR ECMA:

места для чисел с плавающей точкой (статики, элементов массива, и полей классов) хранения имеют фиксированный размер. Поддерживаемые размеры хранилищ - float32 и float64. Всюду в другом (в стеке оценки, как аргументы , в качестве типов возврата и как локальные переменные) числа с плавающей запятой представлены с использованием внутреннего типа с плавающей запятой. В каждом такой экземпляр номинальный тип переменной или выражения равен либо R4, либо R8, но его значение может быть представлено внутри с дополнительным диапазоном и/или точностью . Размер внутреннего с плавающей запятой зависит от реализации, может варьироваться, и должен иметь точность, по меньшей мере такую ​​же, как у переменной или . Неявное расширение преобразования в внутреннее представление из float32 или float64 выполняется, когда эти типы загружаются из хранилища. Внутреннее представление - , как правило, собственный размер для аппаратного обеспечения или, как требуется для , эффективная реализация операции.

Чтобы перевести интерлейкин генерироваться будет таким же (за исключением того, что режим отладки вставки НОП в местах для обеспечения точки останова возможно, он также может намеренно поддерживать временную переменную, освободить режим считает ненужным.) ... но JITter менее агрессивен, когда имеет дело со сборкой, отмеченной как отладка. Выпускные сборки имеют тенденцию перемещать больше плавающих значений в 80-битные регистры; отладочные сборки, как правило, читаются непосредственно из 64-разрядной памяти.

Если вы хотите «точное» число с плавающей точкой печати, используйте string.Substring(...) вместо Math.Round

+0

спасибо, почему вы думаете, что это работает в одной среде? –

+0

, потому что ваше значение может быть либо 64-битным (debug-FPU), либо 80-битным (release - SSE), или что-то еще, в зависимости от оптимизации –

2

IEEE754 двойной точности с плавающей запятой не может представлять 20.9032. Наиболее точное представление - 2.09031999999999982264853315428E1, и это то, что вы видите на своем выходе.

Не форматируйте числа с круглым, а используйте строковый формат метода double.ToString (string formatString).

См msdn documentation из Double.ToString методы (String)

Разница между Release и Debug сборками может быть некоторыми оптимизации, что может быть сделано для построения релиза, но это способ подробных, на моем взгляде. На мой взгляд, основная проблема заключается в том, что вы пытаетесь форматировать текстовый вывод с помощью математической операции. Извините, но я не знаю, что в деталях создает другое поведение.

+0

, почему он работает в одной среде? –

+0

Хороший ответ, но он не отвечает на вопрос, почему он отличается в режиме выпуска и отладки. –

Смежные вопросы