Преобразование строки в Int и потеря точности

#c#

#c#

Вопрос:

У меня небольшая проблема с преобразованием строки типа «129.70» в целое число (в данном случае 12970). Это функция, которую я написал :

 public static int valToInt(string v)
{
    int tmp = (int)(double.Parse(v, new System.Globalization.CultureInfo("en-US")) * 1000);
    return tmp / 10;
}
  

Я использовал * 1000, а затем / 10, чтобы решить такую проблему, и это хорошо работает в 99% случаев, но 129,70 кажется критическим значением и преобразуется в 12969.
Есть ли способ выполнить преобразование без каких-либо потерь? Поскольку это денежные значения, то в них будет не более двух десятичных цифр…

Комментарии:

1. Используйте десятичную дробь для денежных значений. Он также имеет метод Parse () и не потеряет точность.

2. Всякий раз, когда вы имеете дело с денежными значениями, используйте decimal вместо double — оно хранится как базовое число 10 за кулисами, поэтому потерь при преобразовании из двоичного представления не будет.

3. decimal.Parse(«129.70») = 12970 и все в порядке. decimal.Parse(«5») = 5 … хотя это не совсем нормально 🙂

Ответ №1:

Почему бы не убрать десятичный знак из строки, а затем проанализировать ее?

Комментарии:

1. это было бы моим решением, если вы действительно должны использовать целое число. stringname.Replace(".", "") затем проанализируйте его как Int

Ответ №2:

 public static int valToInt(string v)
{     
    return (int)(Decimal.Parse(v, new System.Globalization.CultureInfo("en-US")) * 100m);     
} 
  

Вам действительно нужен «смещенный» int? Рассмотрите возможность оставить значение как десятичное.

Ответ №3:

Я прочитал много комментариев о том, «почему» целые и двойные числа «менее точны», чем десятичные, но короткий ответ — использовать десятичные дроби. Для некоторых ссылок о том, почему:

  1. http://msdn.microsoft.com/en-us/library/364x0z75(v=vs.80).aspx
  2. http://msdn.microsoft.com/en-us/library/yht2cx7b(v=vs.80).aspx

Ответ №4:

Значения с плавающей запятой по своей сути имеют ограничения по точности. Умножение на 1000 не сделает его более точным, оно просто не может точно представить число.

Поскольку вы усекаете число при преобразовании его в int , вы будете преувеличивать любые потери точности. Если значение равно чему-то вроде 129699.99999999 перед преобразованием его в int , вы просто разделите десятичные дроби и в итоге получите 129699. Это также можно было бы округлить до правильного значения, но целочисленное деление сократит еще больше данных, давая вам 12969 вместо 12970.

Просто умножьте на 100, округлите и преобразуйте в int :

 public static int valToInt(string v) {
    return (int)Math.Round(Double.Parse(v, new System.Globalization.CultureInfo("en-US")) * 100.0);
}
  

Ответ №5:

попробуйте это, это так просто…

 public static int valToInt(string v)
{
    return int.Parse(v.Replace(".",""));
}