#c# #biginteger
#c# #biginteger
Вопрос:
Я пытался понять, почему этот код, похоже, работает так, как он работает. Для меня это похоже на ошибку в BigInteger
классе, но я могу ошибаться.
using System.Numerics;
using System.Globalization;
BigInteger resu<
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
Комментарии:
1. «независимо от того, какое число я использую, мантисса всегда равна 9999». Вы имеете в виду показатель ?
2. Вот ваша проблема , все, что превышает 1000, получает показатель 9999
3. Теперь, когда мы это знаем, любое решение будет зависеть от того, что вы на самом деле пытаетесь сделать или, в частности, что вам нужно сделать.
4. Да, это определенно так, спасибо. По сути, то, что я пытаюсь сделать, это проанализировать кучу этих больших чисел в том же формате 0.00e0000, чтобы я мог использовать их как BigIntegers для сравнения и математических операций. Возможно, я смогу придумать умный способ разбить их на части, потому что я не думаю, что проблема в основном связана с классом BigInteger, а с этой реализацией TryParse .
Ответ №1:
Причина, по которой это не работает, заключается не столько в ошибке как таковой, сколько в ограничении ParseNumber
if (exp > 1000)
{
exp = 9999;
while (ch >= '0' amp;amp; 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
Примечание : это не решение каждой проблемы, ему не хватает подходящей степени отказоустойчивости, и это только пример возможного решения.