2016-08-01 11 views
3

Там уже находятся решения этой проблемы для малых чисел:разность двух больших чисел C#

I Подведем итог ответа всем:

Math.Abs(a - b) 

Проблема при больших номерах это дает неправильный ответ (посредством переполнения). Хуже того, если (a - b) = Int32.MinValue, то Math.Abs сбоев с исключением (потому что Int32.MaxValue = Int32.MinValue - 1). Его специфическая природа приводит к трудновоспроизводимым ошибкам.

Возможно, мне не хватает известной функции библиотеки, но есть ли способ определить разницу безопасно?

+6

BigInteger - https://msdn.microsoft.com/en-us/library/system.numerics.biginteger(v=vs.110).aspx –

+5

Что касается преобразования в длинный (Int64), а затем нахождения разницы ? – Igor

+0

Есть a и b Int32 или Int64? – Liam

ответ

0

BigInteger был представлен в .Net 4.0.

Существует несколько версий с открытым исходным кодом, доступных в более низких версиях .NET Framework, однако вам было бы разумно идти со стандартом.

Если Math.Abs все еще дает вам горе, вы можете реализовать эту функцию самостоятельно; если число отрицательное (a - b < 0), просто обрезайте отрицательный символ так, чтобы он был без знака.

Кроме того, вы пробовали использовать парные пары? Они имеют гораздо большие значения.

2

Как было предложено другими, использовать BigInteger, как это определено в System.Numerics (вы должны включать пространство имен в Visual Studio) Тогда вы можете просто сделать:

BigInteger a = new BigInteger(); 
BigInteger b = new BigInteger(); 
// Assign values to a and b somewhere in here... 
// Then just use included BigInteger.Abs method 
BigInteger result = BigInteger.Abs(a - b); 

ответ Джереми Томпсона остается в силе , но обратите внимание, что пространство имен BigInteger включает метод абсолютного значения, поэтому не должно быть необходимости в специальной логике. Кроме того, Math.Abs ​​ожидает десятичное число, так что это даст вам горе, если вы попытаетесь пройти в BigInteger.

Имейте в виду, что существуют предостережения от использования BigIntegers. Если у вас есть смехотворно большое количество, C# попытается выделить для него память, и вы можете столкнуться с исключениями из памяти. С другой стороны, BigIntegers великолепны, потому что объем выделенной им памяти динамически изменяется по мере увеличения числа.

Отъезд Microsoft ссылка здесь для получения дополнительной информации: https://msdn.microsoft.com/en-us/library/system.numerics.biginteger(v=vs.110).aspx

1

Вопрос в том, как вы хотите провести различие между двумя большими числами? Если вы вычисляете разницу между двумя подписанными длинными (64-разрядными) целыми числами, например, и разница не будет вписываться в подписанное длинное целое число, как вы собираетесь его хранить?

long a = +(1 << 62) + 1000; 
long b = -(1 << 62); 

long dif = a - b; // Overflow, bit truncation 

Разница между a и b шире, чем 64 бит, поэтому, когда он хранится в длинное целое, его высокого порядка биты отсекаются, и вы получите странное значение для dif.

Другими словами, вы не можете сохранить все возможные различия между значащими целыми значениями заданной ширины в знаковое целое с той же шириной. (Вы можете хранить только половину всех возможных значений, другая половина требует дополнительного бита.)

Ваши варианты должны либо использовать более широкий тип, чтобы удерживать разницу (что не поможет вам, re уже используют самый широкий целочисленный тип long) или использовать другой арифметический тип. Если вам нужно как минимум 64 знака с битами точности, вам, вероятно, потребуется использовать BigInteger.

0

Это альтернатива, которая может быть вам интересна, но находится в пределах определенного размера. В этом примере используется Int32 и использует побитовые операторы для достижения разницы, а затем абсолютное значение. Эта реализация терпима к вашему сценарию, где a - b равно минимальному значению int, оно, естественно, возвращает значение min int (не намного больше, что вы можете сделать, не отбрасывая вещи более крупному типу данных). Я не думаю, что это так хорошо, как ответ, используя BigInteger, но это удовольствие играть с, если ничего другого:

static int diff(int a, int b) 
    { 
     int xorResult = (a^b); 
     int diff = (a & xorResult) - (b & xorResult); 
     return (diff + (diff >> 31))^(diff >> 31); 
    } 

Вот некоторые случаи, я побежал через, чтобы играть с поведением:

 Console.WriteLine(diff(13, 14)); // 1 
     Console.WriteLine(diff(11, 9)); // 2 
     Console.WriteLine(diff(5002000, 2346728)); // 2655272 
     Console.WriteLine(diff(int.MinValue, 0)); // Should be 2147483648, but int data type can't go that large. Actual result will be -2147483648.