Математика с большими числами и Biginteger врет

169
28 октября 2018, 16:30

Нужно производить простые арифметические действия над большими числами на C#. Использовал библиотеку System.Numerics. Но он не верно считает. Например

BigInteger first = BigInteger.Parse("1459141956031776814097256491377265401586541003894843279763498785157880955654141795");
BigInteger second = BigInteger.Parse("22248470822666314938692568397119675677137950638191323448941735236079264477232");
BigInteger result = first / second;

Получаю результат = 65583. Теперь если число из переменной first разделить на 65583 должно получиться число second, но это не так, получается совершенно другое число. Как реализовать, чтобы правильно посчитать?

Answer 1

Сделаем небольшое исследование, попробуем просчитать хотя бы приблизительный результат деления. У каждого числа отбрасываем последние 72 знака. Тогда у нас остается: 1459141956 / 22248 с такими числами можно оперировать в калькуляторе, что примерно равно: 65585. По-этому, мне кажется, что считает вполне правильно.

Дополнено: Если Вас смущает отсутствие дробной части числа, но необходимо ознакомится с правилами деления чисел в C# , особенно этой частью:

When you divide two integers, the result is always an integer. 
For example, the result of 7 / 3 is 2. 
This is not to be confused with floored division, 
as the / operator rounds towards zero: -7 / 3 is -2.
To obtain a quotient as a rational number, use the float, double, or decimal types

То есть, Вам нужно вместо BigInteger для second и result использовать тип с плавающей точкой: float, double или же его аналог в библиотеке больших чисел.

Answer 2

Вариант 1. Приведение к типу double.

BigInteger first = BigInteger.Parse("1459141956031776814097256491377265401586541003894843279763498785157880955654141795");
BigInteger second = BigInteger.Parse("22248470822666314938692568397119675677137950638191323448941735236079264477232");
Console.WriteLine($"Result: {(double)first / (double)second}");
Console.ReadKey();

Да, точность уменьшается, но всё равно остаётся достаточно большой; Вы же не ракету в космос запускаете?..

Вариант 2. Использование BigInteger.DivRem().

Метод DivRem() возвращает остаток от деленя двух BigInteger, но остаток - это не дробная часть.

BigInteger first = BigInteger.Parse("1459141956031776814097256491377265401586541003894843279763498785157880955654141795");
BigInteger second = BigInteger.Parse("22248470822666314938692568397119675677137950638191323448941735236079264477232");
BigInteger quotient = BigInteger.DivRem(first, second, out BigInteger remainder);
Console.WriteLine($"Result: {quotient}\nRemainder: {remainder}");    
Console.ReadKey();

Вариант 3. Использование библиотеки BigRational.

Numerics.BigRational result = new Numerics.BigRational(first, second);

Я считаю, что первый вариант - наилучшее решение.

Сам с Ruby не работал, но видел как знакомый на курсах показывал калькулятор с нереально большими числами. Может можно написать .dll на похожем языке и подключить в ваше приложение, но это так, мысли в слух.

READ ALSO
System.NullReferenceException: “Ссылка на объект не указывает на экземпляр объекта.”

System.NullReferenceException: “Ссылка на объект не указывает на экземпляр объекта.”

Пытаюсь победить ошибку уже 4 день, уже весь интернет облазил, пересмотрел много решений, но так и не приблизился к решению проблемы :(

265
Мульти тач как в Piano Tile

Мульти тач как в Piano Tile

Каким методом реализовать данную функцию? Если touchcounts, то отслеживает только количество нажатий

164
Запись в файл без перезагрузки формы

Запись в файл без перезагрузки формы

Есть форма "form" с несколькими строками, не могу сделать, так, чтобы при нажатии на кнопку submit форма не перезагружалась, а просто записала данные...

186