首页 > 解决方案 > BigInteger 解析指数大于 1000 的科学记数法,结果为 9999

问题描述

我一直在为为什么这段代码似乎可以正常工作而苦苦挣扎。对我来说,这看起来像是BigInteger课堂上的一个错误,但我可能是错的。

using System.Numerics;
using System.Globalization;

BigInteger result;
if (!BigInteger.TryParse("2.36e6007", NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint, null, out result)) result = 0;
Debug.WriteLine(result.ToString("0.00e0000"));

我始终得到2.36e9999结果,无论我使用什么数量级总是9999. 我不确定这是一个错误还是我在这里做错了什么。我在解析后尝试了一个断点并检查了该值,它确实9999有零,所以如果它是一个错误,它就在BigInteger.TryParse

标签: c#biginteger

解决方案


这不起作用的原因与其说是一个错误本身,不如说是一个限制ParseNumber

if (exp > 1000)
{
   exp = 9999;
   while (ch >= '0' && ch <= '9')
   {
      ch = *++p;
   }
}

如您所见,任何超过的指数1000都将默认为 的指数9999

一种方法(取决于您的需要)是自己解析指数并BigInteger从其组成部分创建指数。这样做的缺点是它不会处理超出其非常狭窄范围的任何变化(您需要添加胡椒和盐来调味)。它也可能会慢很多。

给定

public static (decimal multiplier, int exponent) Decompose(string value)
{
   var split = value.Split('e');
   return (decimal.Parse(split[0]), int.Parse(split[1]));
}
public static int GetDecimalPlaces(decimal value) 
   => BitConverter.GetBytes(decimal.GetBits(value)[3])[2];

public static BigInteger ParseExtended(string value)
{
   var (multiplier, exponent) = Decompose(value);

   var decimalPlaces = GetDecimalPlaces(multiplier);
   var power = (int) Math.Pow(10, decimalPlaces);

   return (BigInteger.Pow(10, exponent) * (int) (multiplier * power)) / power;
}

用法

Console.WriteLine(ParseExtended("2.36e6007").ToString("0.00e0000"));

输出

2.36e6007

完整的演示在这里

注意:这并不是所有问题的解决方案,它缺乏适当的容错能力,并且只是可能解决方案的一个示例。


推荐阅读