1

I'm having a problem with modulo from int which has 31 chars. It seems to bug out on
Int64 convertedNumber = Int64.Parse(mergedNumber); with Value was either too large or too small for an Int64. (Overflow Exception). How to fix it so that modulo doesn't bug out ?

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;
    }

}
MadBoy
  • 10,824
  • 24
  • 95
  • 156

4 Answers4

7

The max value for Int64 is 9223372036854775807 (19 characters when printed). You will probably want to use BigInteger instead (which was introduced in .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;
}
Fredrik Mörk
  • 155,851
  • 29
  • 291
  • 343
  • Thanks this seems to work just fine. Thanks for the MathMod change too. Will test it a bit more and see how it goes ;-) – MadBoy Apr 14 '11 at 11:52
2

Int64.MaxValue is 9,223,372,036,854,775,807 that's 19 characters. So you just can't fit that in. I suggest looking at this question for working with big numbers.

Community
  • 1
  • 1
Vincent Vancalbergh
  • 3,267
  • 2
  • 22
  • 25
  • -1. This question should definitely be solved without the use of BigInteger. – Doc Brown Apr 14 '11 at 11:30
  • 2
    I object. My answer is perfectly workable. Vote up the correct answer, vote down wrong answers. – Vincent Vancalbergh Apr 14 '11 at 11:34
  • Actually, you vote down answers that are "not useful". Check the tooltip. The idea is that the *best* answers rise to the top of the page. The point others have made is that `BigInteger` is the *better* solution, not that yours is wrong. – Cody Gray - on strike Apr 14 '11 at 11:43
  • IMHO you answer points the OP in the wrong direction. Read my answer for a pretty simple solution that does not even need Int64. – Doc Brown Apr 14 '11 at 11:51
  • I agree your answer is better, but then it will get upvoted. No note to downvote other answers to push yours up. – Vincent Vancalbergh Apr 14 '11 at 12:06
  • 1
    I think my downvote was a little bit overreacted, of course, but SO does not let me remove it now any more. – Doc Brown Apr 14 '11 at 13:01
2

Try this function instead of "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;
    }

(since all of your numbers are positive, there is no point in using Math.Abs, as in your original MathMod function).

Use it this way:

modulo = ModString(mergedNumber,97);

This should works with all versions of .NET since 1.1, without the need of BigInteger.

Doc Brown
  • 19,739
  • 7
  • 52
  • 88
1

The answer you are looking for is demonstrated here. It includes various manners to calculate the modulus for huge numbers. I used similar methods as described here for international bank account numbers.

A direct link to someone who has a copy pastable method is here.

Community
  • 1
  • 1
Jaapjan
  • 3,365
  • 21
  • 25