Skip to content

Commit

Permalink
Тутор: Уменьшаем шанс промаха при делении | Синхронизировал тутор с б…
Browse files Browse the repository at this point in the history
…иблиотекой
  • Loading branch information
1vanK committed Apr 15, 2024
1 parent c9bf455 commit 7db06e2
Show file tree
Hide file tree
Showing 3 changed files with 390 additions and 3 deletions.
13 changes: 10 additions & 3 deletions big_int.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ static Digit div_chunk(const vector<Digit>& chunk, const vector<Digit>& denomina

// Третья цифра куска
DDigit chunk_digit_3 = (chunk.size() == denominator.size())
? chunk[chunk.size() - 2] // Старшая цифра куска - 0, но его нет в массиве
? chunk[chunk.size() - 2] // Старшая цифра куска = 0, но её нет в массиве
: chunk[chunk.size() - 3];

// Вторая цифра знаменателя
Expand All @@ -260,8 +260,8 @@ static Digit div_chunk(const vector<Digit>& chunk, const vector<Digit>& denomina
// Делим две старшие цифры куска на старшую цифру знаменателя
DDigit digit = chunk_2_digits / denominator_digit_1;

// Остаток может быть больше base
DDigit remainder = chunk_2_digits - digit * denominator_digit_1;
// Остаток (может быть больше base)
DDigit remainder = chunk_2_digits - digit * denominator_digit_1; // chunk_2_digits % denominator_digit_1

// Уменьшаем цифру, если она точно слишком большая
if (digit == base || digit * denominator_digit_2 > remainder * base + chunk_digit_3)
Expand All @@ -270,10 +270,17 @@ static Digit div_chunk(const vector<Digit>& chunk, const vector<Digit>& denomina
remainder += denominator_digit_1;

if (remainder < base && (digit == base || digit * denominator_digit_2 > remainder * base + chunk_digit_3))
{
--digit;

#ifndef NDEBUG
remainder += denominator_digit_1;
#endif
}
}

assert(digit < base);
assert(digit * denominator_digit_2 <= remainder * base + chunk_digit_3);

// Теперь проверяем, нет ли промаха на 1
if (first_is_less(chunk, mul_magnitudes(vector<Digit>{(Digit)digit}, denominator)))
Expand Down
9 changes: 9 additions & 0 deletions docs/4_long_div.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,15 @@

Реализация: [4_long_div_4.cpp](4_long_div_4.cpp).

### Оптимизация 4

Предыдущую оптимизацию можно улучшить, дополнительно изучив ещё по одной цифре числителя и знаменателя.
Это приведёт к тому, что `примерная_цифра` почти всегда будет совпадать с `искомой_цифрой`.
И лишь с вероятностью `2 / base` `примерная_цифра` будет больше `искомой_цифры` на 1.
То есть чем больше основание СС, тем меньше вероятность промаха.

Реализация: [4_long_div_5.cpp](4_long_div_5.cpp).

Литература:
1. https://ru.wikipedia.org/wiki/Деление_столбиком
2. https://en.wikipedia.org/wiki/Long_division
Expand Down
Loading

0 comments on commit 7db06e2

Please sign in to comment.