Почему я не могу разделить BigInt с другим BigInt и сохранить его в переменной, которую я инициализировал нулем? - PullRequest
0 голосов
/ 19 июня 2019

У меня есть следующий фрагмент кода:

use num_bigint::*; // 0.2.2
use num_traits::*; // 0.2.8
use std::ops::*;

fn xgcd(b: &BigInt, a: &BigInt) -> (BigInt, BigInt, BigInt) {
    let mut x0: BigInt = One::one();
    let mut x1: BigInt = Zero::zero();
    let mut y0: BigInt = Zero::zero();
    let mut y1: BigInt = One::one();
    let mut q = 0;
    while a != Zero::zero() {
        q = b.div(a);
        b = a;
        a = &b.rem(a);
        x0 = x1;
        x1 = x0 - q * x1;
        y0 = y1;
        y1 = y0 - q * y1;
    }
    return (*b, x0, y0);
}

выдает следующую ошибку:

error[E0308]: mismatched types
  --> src/lib.rs:12:13
   |
12 |         q = b.div(a);
   |             ^^^^^^^^ expected integer, found struct `num_bigint::bigint::BigInt`
   |
   = note: expected type `{integer}`
              found type `num_bigint::bigint::BigInt`

Я посмотрел документацию num::BigInt и там говорится, что на самом деле существует метод div с BigInt в качестве параметра, но каким-то образом компилятор решает не использовать это и вместо этого говорит мне, что я не могу разделить BigInt с BigInt. Есть ли способ исправить это?

1 Ответ

4 голосов
/ 19 июня 2019

и вместо этого говорит мне, что я не могу разделить BigInt на BigInt

Это не так.Он говорит вам, что результат от деления двух равен BigInt, и для него требуется {integer}.Это потому, что ваша переменная q была объявлена ​​как целое число, а не BigInt.Следовательно, результат деления должен быть неким встроенным целым числом ({integer}), а результатом деления BigInt на BigInt будет еще один BigInt.

Вы использовали Zero::zero везде, поэтому неясно, почему вы не использовали его здесь.К счастью, вам не нужно ничего устанавливать, потому что вы все равно не должны инициализировать его до тех пор, пока внутри цикла:

use num_bigint::*; // 0.2.2
use num_traits::*; // 0.2.8

fn xgcd(b: &BigInt, a: &BigInt) -> (BigInt, BigInt, BigInt) {
    let mut a = a.clone();
    let mut b = b.clone();
    let mut x0 = BigInt::one();
    let mut x1 = BigInt::zero();
    let mut y0 = BigInt::zero();
    let mut y1 = BigInt::one();

    while !a.is_zero() {
        let q = &b / &a;
        b = a.clone();
        a = &b % &a;
        x0 = x1.clone();
        x1 = &x0 - &q * x1;
        y0 = y1.clone();
        y1 = &y0 - &q * y1;
    }

    (b, x0, y0)
}

Изменения включают в себя:

  • Используются операторные формывместо имен методов (например, / против div).
  • Был добавлен ряд вызовов .clone().Я не гарантировал, что это было минимально возможное количество клонов, поэтому проверьте, что.
  • Для предотвращения клонов в других местах было добавлено число &.
  • Zero::is_zero может быть быстрее, чем создание значения и сравнение его.
  • Используется более короткий синтаксис BigInt::zero().

См. Также:

...