2

I want to make

BigInteger.ModPow(1/BigInteger, 2,5);

but 1/BigInteger always return 0, which causes, that the result is 0 too. I tried to look for some BigDecimal class for c# but I have found nothing. Is there any way how to count this even if there is no BigDecimal?

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
MartinS
  • 751
  • 3
  • 12
  • 27
  • How possible `1/BigInteger` returns `0` ?. `BigInters` default value is `0`. It should thrown `DivideByZeroException`. – Soner Gönül Jan 06 '13 at 11:18
  • From the little I know of El Gamal, I don't think the literal multiplicative inverse is what you're looking for. – Rawling Jan 06 '13 at 11:23
  • @SonerGönül Well, it should not compile because it doesn't say `new BigInteger()`, neither `default(BigInteger)`. It should complain that a "type" is used like a "variable" in the expression. – Jeppe Stig Nielsen Jan 06 '13 at 12:05
  • @JeppeStigNielsen In this case, `BigInteger` doesn't look like a variable. This looks like a class usage. – Soner Gönül Jan 06 '13 at 12:07
  • @SonerGönül Like I said, it **is** a "type" (it's a `struct` in this case), and therefore it's disallowed to use it **as if** it were a variable. – Jeppe Stig Nielsen Jan 06 '13 at 12:08
  • Use something else instead of Integer. How about double? – Allan Spreys Jan 06 '13 at 11:08
  • Double is too short for division by BigInteger – MartinS Jan 06 '13 at 11:08
  • @MartinŠevic Depends on what you want. Suppose your denominator is a `BigInteger` with less than 300 decimal figures, then the division of `1` by the corresponding double works OK. Precision is lost, but magnitude is OK. But with e.g. 400 decimal figures, `double` will over-/underflow to infinity or zero. – Jeppe Stig Nielsen Jan 06 '13 at 11:50
  • Microsoft Solver Foundation has a rational class; if you want to represent exact rational numbers, it's quite useful. You can download it for free. – Eric Lippert Jan 06 '13 at 13:50

3 Answers3

12

1/a is 0 for |a|>1, since BigIntegers use integer division where the fractional part of a division is ignored. I'm not sure what result you're expecting for this.

I assume you want to modular multiplicative inverse of a modulo m, and not a fractional number. This inverse exists iff a and m are co-prime, i.e. gcd(a, m) = 1.

The linked wikipedia page lists the two standard algorithms for calculating the modular multiplicative inverse:

  • Extended Euclidean algorithm, which works for arbitrary moduli
    It's fast, but has input dependent runtime.

    I don't have C# code at hand, but porting the pseudo code from wikipedia should be straight forward.

  • Using Euler's theorem:
    $i^{-1} = i^{φ(n)-1}$
    This requires knowledge of φ(m) i.e. you need to know the prime factors of m. It's a popular choice when m is a prime and thus φ(m) = m-1 when it simply becomes $a^{-1} = a^{p-2}$. If you need constant runtime and you know φ(m), this is the way to go.

    In C# this becomes BigInteger.ModPow(a, phiOfM-1, m)

Community
  • 1
  • 1
CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
1

The overload of the / operator chosen, is the following:

public static BigInteger operator /(
        BigInteger dividend,
        BigInteger divisor
)

See BigInteger.Division Operator. If the result is between 0 and 1 (which is likely when dividend is 1 as in your case), because the return value is an integer, 0 is returned, as you see.

What are you trying to do with the ModPow method? Do you realize that 2,5 are two arguments, two and five, not "two-point-five"? Is your intention "take square modulo 5"?

If you want floating-point division, you can use:

1.0 / (double)yourBigInt

Note the cast to double. This may lose precision and even "underflow" to zero if yourBigInt is too huge.

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
0

For example you need to get d in the next:
3*d = 1 (mod 9167368)

this is equally:
3*d = 1 + k * 9167368, where k = 1, 2, 3, ...

rewrite it:
d = (1 + k * 9167368)/3

Your d must be the integer with the lowest k.
Let's write the formula:
d = (1 + k * fi)/e

public static int MultiplicativeInverse(int e, int fi)
        {
            double result;
            int k = 1;
            while (true)
            {
                result = (1 + (k * fi)) / (double) e;
                if ((Math.Round(result, 5) % 1) == 0) //integer
                {
                    return (int)result;
                }
                else
                {
                    k++;
                }
            }
        } 

let's test this code:

Assert.AreEqual(Helper.MultiplicativeInverse(3, 9167368), 6111579); // passed
Yuliia Ashomok
  • 8,336
  • 2
  • 60
  • 69