Преобразование экспоненциального числа в десятичное 1.11111117E + 9 - конечные цифры становятся равными нулю - PullRequest
2 голосов
/ 18 января 2011

Я пытаюсь конвертировать и экспоненциальное число 1.11111117E + 9, которое на самом деле является десятизначным числом '1111111111'.Когда я пытаюсь преобразовать это экспоненциальное число, используя метод decimal.TryParse, последние три цифры равны нулю, а число равно ' 111111000 '.Это происходит с любым 10-значным числом.

   decimal amount;
   decimal.TryParse("1.11111117E+9", NumberStyles.Any, null, out amount);

Это странно, но я не могу понять, в чем здесь проблема, кто-нибудь может сказать мне, что в этом плохого?

Редактировать: Извините за вводящий в заблуждение вопрос.Поскольку Хенрик , упомянутый в его ответе, является именно тем, с чем я сталкиваюсь.

float f = 1111111111;
string s = f.ToString();
decimal amount;
decimal.TryParse(s, NumberStyles.Any, null, out amount);

Это всегда вернет 1111111000?Как мне решить эту проблему, чтобы получить правильное значение?Измените его на Double или Decimal для типа данных с плавающей точкой. Это решение или что-то еще?

Ответы [ 4 ]

7 голосов
/ 18 января 2011

Обойти значение с плавающей запятой легко ...

float f = 1111111111;
string s = f.ToString("r"); // r = roundtrip
float g = float.Parse(s);

Теперь f и g будут одинаковыми ... но это не значит, что любое из значений точно1111111111 ... потому что это значение не может быть представлено как число с плавающей точкой .Ближайшее значение, точно представляемое в виде числа с плавающей точкой, это 1111111168 ... вот почему вы получаете 7 в конце научного представления.

По сути, вам не следует использовать float для этого впервое место.Из документов для System.Single :

По умолчанию значение Single содержит только 7 десятичных цифр точности, хотя внутренне поддерживается максимум 9 цифр.

Поэтому попытка сохранить 10-значное число и ожидать, что он будет сохранен в точности, является делом дурака.

Трудно сказать, следует ли использовать double или decimal -зависит от того, какую ценность вы действительно пытаетесь сохранить.Если это «естественное» значение, такое как вес или рост, я бы выбрал double.Если это «человеческая» ценность, такая как цена, я бы использовал decimal.

4 голосов
/ 18 января 2011

Это

decimal amount;
decimal.TryParse("1.11111117E+9", NumberStyles.Any, 
    CultureInfo.InvariantCulture, out amount);

устанавливает значение 1111111170M, как и ожидалось.

Обратите внимание на CultureInfo.InvariantCulture, поэтому оно не зависит от ваших локальных настроек.

Обновление: Я подозреваю, что ваш реальный код выглядит примерно так:

float f = 1111111111;
string s = f.ToString();
decimal amount;
decimal.TryParse(s, NumberStyles.Any, null, out amount);

f отображается в отладчике как 1.11111117e + 9, s равно 1.111111e + 9 и сумма 1111111000M.Причиной всего этого является ограниченная точность поплавка.

2 голосов
/ 21 августа 2013

Попробуй это, У меня лучше работает

 decimal dec = Decimal.Parse("1.11111117E+9", System.Globalization.NumberStyles.Any);
0 голосов
/ 18 января 2011

Вы должны разобрать double, а не decimal. В научной нотации нет места с decimal.

Обновление: точное целочисленное значение 1111111170. Не 111111111, что примерно в 10 раз меньше, чем должно быть.

...