1/BigInteger в C#
Я хочу сделать
BigInteger.ModPow(1/BigInteger, 2,5);
но 1/BigInteger
всегда возвращайся 0
, что приводит к тому, что результат 0
тоже. Я пытался искать некоторые BigDecimal
класс для C#, но я ничего не нашел. Есть ли способ, как посчитать это, даже если нет BigDecimal
?
3 ответа
1/a
0 для |a|>1, так как BigIntegers
используйте целочисленное деление, где дробная часть деления игнорируется. Я не уверен, какой результат вы ожидаете для этого.
Я предполагаю, что вы хотите, чтобы модульное мультипликативное обратное a
по модулю m
а не дробное число. Это обратное существует, если a
а также m
являются взаимно простыми, т.е. gcd(a, m) = 1
,
На странице связанной википедии перечислены два стандартных алгоритма для вычисления модульного обратного мультипликатива:
Расширенный евклидов алгоритм, который работает для произвольных модулей
Это быстро, но имеет зависящее от входа время выполнения.У меня нет кода C# под рукой, но портирование псевдокода из Википедии должно быть простым.
Используя теорему Эйлера:
Это требует знания φ(m), т. Е. Вам нужно знать основные множители m. Это популярный выбор, когдаm
простое число и, следовательно, φ(m) = m-1, когда оно просто становится , Если вам нужно постоянное время выполнения, и вы знаете φ(м), это путь.В C# это становится
BigInteger.ModPow(a, phiOfM-1, m)
Перегрузка /
оператор, выбранный следующим образом:
public static BigInteger operator /(
BigInteger dividend,
BigInteger divisor
)
Смотрите BigInteger.Division Operator. Если результат между 0
а также 1
(что, вероятно, когда dividend
является 1
как в вашем случае), потому что возвращаемое значение является целым числом, 0
возвращается, как видите.
Что вы пытаетесь сделать с ModPow
метод? Вы понимаете, что 2,5
два аргумента, два и пять, а не "две точки пять"? Ваше намерение "взять квадрат по модулю 5"?
Если вы хотите деление с плавающей точкой, вы можете использовать:
1.0 / (double)yourBigInt
Обратите внимание на приведение к double
, Это может потерять точность и даже "опуститься" до нуля, если yourBigInt
слишком велик
Например, вам нужно получить d в следующем:
3 * d = 1 (мод 9167368)
это в равной степени:
3 * d = 1 + k * 9167368, где k = 1, 2, 3, ...
переписать это:
d = (1 + k * 9167368)/ 3
Ваше d должно быть целым числом с самым низким k.
Напишем формулу:
д = (1 + к * фи)/ е
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++;
}
}
}
давайте проверим этот код:
Assert.AreEqual(Helper.MultiplicativeInverse(3, 9167368), 6111579); // passed