Модуль от очень большого целого числа С#

У меня проблема с модулем из int, который имеет 31 символ. Кажется, возникла ошибка
Int64 convertedNumber = Int64.Parse(mergedNumber); с Value was either too large or too small for an Int64. (Overflow Exception). Как исправить, чтобы по модулю не глючило?

class GeneratorRachunkow {
    private static string numerRozliczeniowyBanku = "11111155"; // 8 chars
    private static string identyfikatorNumeruRachunku = "7244"; // 4 chars
    private static string stalaBanku = "562100"; // 6 chars

    public static string generator(string pesel, string varKlientID) {      
        string peselSubstring = pesel.Substring(pesel.Length - 5); // 5 chars (from the end of the string);
        string toAttach = varKlientID + peselSubstring;
        string indywidualnyNumerRachunku = string.Format("{0}", toAttach.ToString().PadLeft(13, '0')); // merging pesel with klient id and adding 0 to the begining to match 13 chars
        string mergedNumber = numerRozliczeniowyBanku + identyfikatorNumeruRachunku + indywidualnyNumerRachunku + stalaBanku; // merging everything -> 31 chars
        Int64 convertedNumber = Int64.Parse(mergedNumber);
        Int64 modulo = MathMod(convertedNumber, 97);

        Int64 wynik = 98 - modulo;
        string wynikString = string.Format("{0}", wynik.ToString().PadLeft(2, '0')); // must be 2 chars
        indywidualnyNumerRachunku = wynikString + numerRozliczeniowyBanku + identyfikatorNumeruRachunku + indywidualnyNumerRachunku; 

        return indywidualnyNumerRachunku;
    }
    private static Int64 MathMod(Int64 a, Int64 b) {
        return (Math.Abs(a * b) + a) % b;
    }

}

person MadBoy    schedule 14.04.2011    source источник
comment
Совершенно не по теме, но что это за "разговорный" язык? Я нахожу слово индивидуальный, веселый :)   -  person Darren Young    schedule 14.04.2011
comment
Число из 31 символа... Это также прокомментировано в коде. он суммирует несколько значений.   -  person MadBoy    schedule 14.04.2011
comment
@Darren Польский, смешанный с английским;)   -  person MadBoy    schedule 14.04.2011
comment
@Darren - польский, судя по профилю @MadBoy ;)   -  person Sergi Papaseit    schedule 14.04.2011
comment
и identyfikator! С этого момента я могу взорвать свои Id, просто ради прикола...   -  person Grant Thomas    schedule 14.04.2011


Ответы (4)


Максимальное значение для Int64 равно 9223372036854775807 (19 символов при печати). Вместо этого вы, вероятно, захотите использовать BigInteger (что было представлено в .NET 4):

public static string generator(string pesel, string varKlientID) { 
    // I have cut some code here to keep it short
    BigInteger convertedNumber;
    if (BigInteger.TryParse(mergedNumber , out convertedNumber))
    {
        BigInteger modulo = convertedNumber % 97;           
        // The rest of the method goes here...
    }
    else
    {
        // string could not be parsed to BigInteger; handle gracefully
    }

}

private static BigInteger MathMod(BigInteger a, BigInteger b)
{
    return (BigInteger.Abs(a * b) + a) % b;
}
person Fredrik Mörk    schedule 14.04.2011
comment
Спасибо, кажется, это работает нормально. Спасибо и за изменение MathMod. Попробую еще немного, а там как пойдет ;-) - person MadBoy; 14.04.2011

Int64.MaxValue — 9 223 372 036 854 775 807, то есть 19 символов. Так что вы просто не можете это уместить. Я предлагаю посмотреть на этот вопрос для работы с большими числа.

person Vincent Vancalbergh    schedule 14.04.2011
comment
-1. Этот вопрос обязательно должен решаться без использования BigInteger. - person Doc Brown; 14.04.2011
comment
Я протестую. Мой ответ вполне рабочий. Голосуйте за правильный ответ, голосуйте против неправильных ответов. - person Vincent Vancalbergh; 14.04.2011
comment
На самом деле, вы голосуете за бесполезные ответы. Проверьте всплывающую подсказку. Идея состоит в том, что лучшие ответы поднимаются вверх страницы. Другие считают, что BigInteger - это лучшее решение, а не то, что ваше неверно. - person Cody Gray; 14.04.2011
comment
ИМХО, вы отвечаете, что указываете ОП в неправильном направлении. Прочитайте мой ответ для довольно простого решения, которому даже не нужен Int64. - person Doc Brown; 14.04.2011
comment
Я согласен, что ваш ответ лучше, но тогда за него проголосуют. Нет примечания, чтобы понизить другие ответы, чтобы поднять ваш. - person Vincent Vancalbergh; 14.04.2011
comment
Я думаю, что мое отрицательное мнение, конечно, было немного преувеличенным, но SO больше не позволяет мне удалить его. - person Doc Brown; 14.04.2011

Попробуйте эту функцию вместо "MathMod":

    static int ModString(string x, int y)
    {
        if (x.Length == 0)
            return 0;
        string x2 = x.Substring(0,x.Length - 1); // first digits
        int x3 = int.Parse(x.Substring(x.Length - 1));   // last digit
        return (ModString(x2, y) * 10 + x3) % y;
    }

(поскольку все ваши числа положительные, нет смысла использовать Math.Abs, как в исходной функции MathMod).

Используйте это следующим образом:

modulo = ModString(mergedNumber,97);

Это должно работать со всеми версиями .NET, начиная с 1.1, без необходимости использования BigInteger.

person Doc Brown    schedule 14.04.2011
comment
Интересный подход. Тоже будем тестить. Спасибо! - person MadBoy; 14.04.2011
comment
Дает точно такие же результаты, как и ответы Фредрика. Хотел бы я принять оба. - person MadBoy; 14.04.2011

Ответ, который вы ищете, демонстрируется здесь. Он включает в себя различные способы вычисления модуля для огромных чисел. Я использовал аналогичные методы, описанные здесь, для международных номеров банковских счетов.

Прямая ссылка на кого-то, у кого есть метод копирования и вставки: здесь.

person Jaapjan    schedule 14.04.2011
comment
Дело не в расчете. Он даже не может вставить значение в числовую переменную. Но да, эта вторая ссылка может помочь. - person Vincent Vancalbergh; 14.04.2011