Найдите наименьшее регулярное число, которое не меньше чем N - PullRequest
9 голосов
/ 11 февраля 2012

Обычные числа - это числа, которые равномерно делят степени 60. Например, 60 2 = 3600 = 48 × 75, поэтому и 48, и 75 являются делителями степени 60. Таким образом, они также являются обычными числами.

Это расширение с округлением до следующей степени двух .

У меня есть целочисленное значение N , которое может содержать большие простые множители, и я хочу округлить его до числа, состоящего только из небольших простых факторов (2, 3 и 5)

Примеры:

  • f(18) == 18 == 2<sup>1</sup> * 3<sup>2</sup>
  • f(19) == 20 == 2<sup>2</sup> * 5<sup>1</sup>
  • f(257) == 270 == 2<sup>1</sup> * 3<sup>3</sup> * 5<sup>1</sup>

Каким был бы эффективный способ найти наименьшее число, удовлетворяющее этому требованию?

Используемые значения могут быть большими, поэтому я бы хотел избежать перечисления всех обычных чисел, начиная с 1, или сохранения массива всех возможных значений.

Ответы [ 8 ]

5 голосов
/ 20 августа 2012

Можно получить произвольно тонкий срез последовательности Хэмминга вокруг n-го члена за время ~ n^(2/3) путем прямого перечисления троек (i,j,k), так что N = 2^i * 3^j * 5^k.

Алгоритм работает от log2(N) = i+j*log2(3)+k*log2(5);перечисляет все возможные k с и для каждого из всех возможных j с находит вершину i и, следовательно, тройную (k,j,i) и сохраняет ее в «полосе», если находится внутри заданной «ширины» ниже заданного максимумаЛогарифмическое верхнее значение (когда width <1 может быть не более одного такого <code>i), затем сортирует их по логарифмам.

WP говорит , что n ~ (log N)^3, то есть время выполнения~ (log N)^2.Здесь мы не заботимся о точном положении найденной тройки в последовательности, поэтому все вычисления подсчета из исходного кода могут быть отброшены:

slice hi w = sortBy (compare `on` fst) b where       -- hi>log2(N) is a top value
  lb5=logBase 2 5 ; lb3=logBase 2 3                  -- w<1 (NB!) is log2(width)
  b  = concat                                        -- the slice
      [ [ (r,(i,j,k)) | frac < w ]                   -- store it, if inside width
        | k <- [ 0 .. floor ( hi   /lb5) ],  let p = fromIntegral k*lb5,
          j <- [ 0 .. floor ((hi-p)/lb3) ],  let q = fromIntegral j*lb3 + p,
          let (i,frac)=properFraction(hi-q) ;    r = hi - frac ]   -- r = i + q
                    -- properFraction 12.7 == (12, 0.7)

-- update: in pseudocode:
def slice(hi, w):
    lb5, lb3 = logBase(2, 5), logBase(2, 3)  -- logs base 2 of 5 and 3
    for k from 0 step 1 to floor(hi/lb5) inclusive:
        p = k*lb5
        for j from 0 step 1 to floor((hi-p)/lb3) inclusive:
           q = j*lb3 + p
           i = floor(hi-q)
           frac = hi-q-i                     -- frac < 1 , always
           r = hi - frac                     -- r == i + q
           if frac < w:
              place (r,(i,j,k)) into the output array
   sort the output array's entries by their "r" component
        in ascending order, and return thus sorted array

Перечисливтройки в срезе, это просто вопрос сортировки и поиска, требующий практически O(1) времени (для произвольно тонкого среза), чтобы найти первую тройку выше N.Ну, на самом деле, для постоянной ширины (логарифмической) количество чисел в срезе (члены «верхней коры» в (i,j,k) -пространстве ниже плоскости log(N)) снова равно m ~ n^2/3 ~ (log N)^2, а сортировка занимает m log m время (так что поиск, даже линейный, занимает ~ m время выполнения).Но ширина может быть уменьшена для больших N с, после некоторых эмпирических наблюдений;и постоянные коэффициенты для перечисления троек намного выше, чем для последующей сортировки в любом случае.

Даже при постоянной ширине (логартмике) он работает очень быстро, мгновенно вычисляя 1 000 000-е значение в последовательности Хемминга и миллиардный в 0,05 с.

Первоначальная идея "верхней группы троек" принадлежит Луи Клаудеру, как цитируется в моем посте в блогах DDJ.обсуждение в 2008 году.

обновление: как отмечено GordonBGood в комментариях , нет необходимости для всей группы, носкорее, примерно одно или два значения выше и ниже цели.Алгоритм легко изменить с этой целью.Входные данные также должны быть проверены на наличие числа Хэмминга перед тем, как продолжить работу с алгоритмом, чтобы избежать проблем округления с двойной точностью.Нет проблем округления при сравнении логарифмов чисел Хэмминга, о которых заранее известно, что они различны (хотя при увеличении до триллионной записи в последовательности использует около 14 значащих цифр в значениях логарифма, оставляя только 1-2 цифры, чтобы сэкономить, так что в действительности ситуация может измениться, но для одной миллиардной нам нужно только 11 значащих цифр).

update2: дает двойную точность для логарифмовограничивает это числами от примерно 20 000 до 40 000 десятичных цифр (то есть от 10 триллионных до 100 триллионных чисел Хэмминга).Если это действительно необходимо для таких больших чисел, алгоритм можно переключить обратно на работу с самими целочисленными значениями вместо их логарифмов, что будет медленнее.

5 голосов
/ 11 февраля 2012

Хорошо, надеюсь, в третий раз здесь очарование. Рекурсивный алгоритм ветвления для начального ввода p, где N - это число, которое «строится» в каждом потоке. NB 3a-c здесь запускаются в виде отдельных потоков или иным образом (квази) асинхронно.

  1. Рассчитайте следующую наибольшую степень 2 после p, назовите это R. N = p.

  2. Является ли N> R? Выйти из этой темы. Состоит ли р только из небольших простых факторов? Вы сделали В противном случае перейдите к шагу 3.

  3. После любого из 3a-c перейдите к шагу 4.

    a) Округлить p до ближайшего кратного 2. Это число может быть выражено как m * 2.
    б) округлите p до ближайшего кратного 3. Это число может быть выражено как m * 3.
    c) Округлить p до ближайшего кратного 5. Это число может быть выражено как m * 5.

  4. Перейти к шагу 2 с p = m.

Я пропустил бухгалтерию, чтобы отслеживать N, но это довольно просто, я так понимаю.

Редактировать: Забыл 6, спасибо ypercube.

Редактировать 2: Если бы до 30 (5, 6, 10, 15, 30) осознали, что это не нужно, убрали это.

Редактировать 3: (Последнее, что я обещаю!) Добавлена ​​проверка степени 30, которая помогает предотвратить использование этого алгоритма всей вашей оперативной памяти.

Редактировать 4: изменена сила-30 на степень-2, согласно наблюдениям finnw.

4 голосов
/ 29 октября 2013

Вот решение на Python, основанное на Уилл Несс ответит , но с некоторыми сочетаниями клавиш и использованием чистой целочисленной математики, чтобы избежать ошибок в точности числового пространства журнала:

import math

def next_regular(target):
    """
    Find the next regular number greater than or equal to target.
    """
    # Check if it's already a power of 2 (or a non-integer)
    try:
        if not (target & (target-1)):
            return target
    except TypeError:
        # Convert floats/decimals for further processing
        target = int(math.ceil(target))

    if target <= 6:
        return target

    match = float('inf') # Anything found will be smaller
    p5 = 1
    while p5 < target:
        p35 = p5
        while p35 < target:
            # Ceiling integer division, avoiding conversion to float
            # (quotient = ceil(target / p35))
            # From https://stackoverflow.com/a/17511341/125507
            quotient = -(-target // p35)

            # Quickly find next power of 2 >= quotient
            # See https://stackoverflow.com/a/19164783/125507
            try:
                p2 = 2**((quotient - 1).bit_length())
            except AttributeError:
                # Fallback for Python <2.7
                p2 = 2**(len(bin(quotient - 1)) - 2)

            N = p2 * p35
            if N == target:
                return N
            elif N < match:
                match = N
            p35 *= 3
            if p35 == target:
                return p35
        if p35 < match:
            match = p35
        p5 *= 5
        if p5 == target:
            return p5
    if p5 < match:
        match = p5
    return match

На английском языке: перебирайте все комбинации 5 и 3, быстро находя следующую степень 2> = цель для каждой пары и сохраняя наименьший результат.(Это бесполезная трата времени, чтобы перебрать все возможные кратные 2, если только один из них может быть правильным).Он также возвращается рано, если когда-либо обнаружит, что цель уже является обычным числом, хотя это не является строго необходимым.

Я довольно тщательно протестировал его, проверяя каждое целое число от 0 до 51200000 и сравнивая со спискомв OEIS http://oeis.org/A051037,, а также во многих больших числах, равных ± 1 от обычных чисел и т. д. В SciPy теперь доступно как fftpack.helper.next_fast_len, чтобы найти оптимальные размеры для БПФ (исходный код ).

Я не уверен, что метод журнала быстрее, потому что я не мог заставить его работать достаточно надежно, чтобы протестировать его.Я думаю, что он имеет такое же количество операций, хотя?Я не уверен, но это достаточно быстро.Занимает <3 секунды (или 0,7 секунды с gmpy), чтобы вычислить, что 2 <sup>142 × 3 80 × 5 444 является следующим обычным числом выше 2 2 × 3 454 × 5 249 + 1 (100 000 000-й обычный номер, который имеет 392 цифры)

3 голосов
/ 11 февраля 2012

Вы хотите найти наименьшее число m, равное m >= N и m = 2^i * 3^j * 5^k, где все i,j,k >= 0.

Принимая логарифмы, уравнения можно переписать в виде:

 log m >= log N
 log m = i*log2 + j*log3 + k*log5

Вы можете рассчитать log2, log3, log5 и logN до (достаточно высокой, в зависимости от размера N) точности.Тогда эта проблема выглядит как задача целочисленного линейного программирования , и вы можете попытаться решить ее, используя один из известных алгоритмов для этой NP-сложной задачи.

1 голос
/ 22 ноября 2018

ИЗДАНО / ИСПРАВЛЕНО: Исправлены коды для прохождения scipy тестов :

Вот ответ, основанный на ответе эндолита , но почти исключающий длинные целочисленные вычисления с множественной точностью с помощью логарифмических представлений float64, чтобы выполнить базовое сравнение, чтобы найти тройные значения, которые соответствуют критериям, только прибегая к полной точности сравнения, когда существует вероятность того, что значение логарифма может быть недостаточно точным, что происходит, только если цель очень близка к предыдущему или следующему обычному числу:

import math

def next_regulary(target):
    """
    Find the next regular number greater than or equal to target.
    """
    if target < 2: return ( 0, 0, 0 )
    log2hi = 0
    mant = 0
    # Check if it's already a power of 2 (or a non-integer)
    try:
        mant = target & (target - 1)
        target = int(target) # take care of case where not int/float/decimal
    except TypeError:
        # Convert floats/decimals for further processing
        target = int(math.ceil(target))
        mant = target & (target - 1)

    # Quickly find next power of 2 >= target
    # See https://stackoverflow.com/a/19164783/125507
    try:
        log2hi = target.bit_length()
    except AttributeError:
        # Fallback for Python <2.7
        log2hi = len(bin(target)) - 2

    # exit if this is a power of two already...
    if not mant: return ( log2hi - 1, 0, 0 )

    # take care of trivial cases...
    if target < 9:
        if target < 4: return ( 0, 1, 0 )
        elif target < 6: return ( 0, 0, 1 )
        elif target < 7: return ( 1, 1, 0 )
        else: return ( 3, 0, 0 )

    # find log of target, which may exceed the float64 limit...
    if log2hi < 53: mant = target << (53 - log2hi)
    else: mant = target >> (log2hi - 53)
    log2target = log2hi + math.log2(float(mant) / (1 << 53))

    # log2 constants
    log2of2 = 1.0; log2of3 = math.log2(3); log2of5 = math.log2(5)

    # calculate range of log2 values close to target;
    # desired number has a logarithm of log2target <= x <= top...
    fctr = 6 * log2of3 * log2of5
    top = (log2target**3 + 2 * fctr)**(1/3) # for up to 2 numbers higher
    btm = 2 * log2target - top # or up to 2 numbers lower

    match = log2hi # Anything found will be smaller
    result = ( log2hi, 0, 0 ) # placeholder for eventual matches
    count = 0 # only used for debugging counting band
    fives = 0; fiveslmt = int(math.ceil(top / log2of5))
    while fives < fiveslmt:
        log2p = top - fives * log2of5
        threes = 0; threeslmt = int(math.ceil(log2p / log2of3))
        while threes < threeslmt:
            log2q = log2p - threes * log2of3
            twos = int(math.floor(log2q)); log2this = top - log2q + twos

            if log2this >= btm: count += 1 # only used for counting band
            if log2this >= btm and log2this < match:
                # logarithm precision may not be enough to differential between
                # the next lower regular number and the target, so do
                # a full resolution comparison to eliminate this case...
                if (2**twos * 3**threes * 5**fives) >= target:
                    match = log2this; result = ( twos, threes, fives )
            threes += 1
        fives += 1

    return result

print(next_regular(2**2 * 3**454 * 5**249 + 1)) # prints (142, 80, 444)

Поскольку большинство длинных вычислений с высокой точностью исключено, gmpy не требуется, и в IDEOne вышеуказанному коду для решения эндолита требуется 0,11 секунды вместо 0,48 секунды, чтобы найти следующее регулярное число, большее 100-миллионного, как показано ; это займет 0,49 секунды вместо 5,48 секунды, чтобы найти следующее обычное число после миллиардной (следующее - (761,572,489) после (1334,335,404) + 1), и разница будет увеличиваться по мере увеличения диапазона, так как вычисления с высокой точностью становятся все более дольше для версии с эндолитом по сравнению с почти ни одной здесь. Таким образом, эта версия может вычислить следующее регулярное число из триллионной в последовательности примерно за 50 секунд в IDEOne, где, вероятно, потребуется более часа с версией эндолита.

Английское описание алгоритма почти такое же, как и для версии с эндолитом, отличающееся следующим: 1) вычисляет логарифмическую оценку целевого значения аргумента (мы не можем использовать встроенную функцию log напрямую, поскольку диапазон может быть слишком большим для представления в виде 64-битного плавающего числа), 2) сравнивает значения лог-представления при определении квалификационных значений в пределах оценочного диапазона выше и ниже целевого значения только около двух или трех чисел (в зависимости от округления), 3) сравнивать значения мультиточности только в пределах определенной выше узкой полосы, 4) выводит тройные индексы, а не полное длинное целое число с множественной точностью (будет около 840 десятичных цифр на одну десятую, в десять раз больше, чем на триллионную), которые затем можно легко преобразовать в длинное значение с множественной точностью если требуется.

Этот алгоритм почти не использует память, кроме как для потенциально очень большого целочисленного целевого значения с множественной точностью, значений сравнения промежуточных оценок примерно одинакового размера и расширения выходных данных в три раза, если требуется. Этот алгоритм является улучшением по сравнению с версией эндолита в том, что он успешно использует значения логарифма для большинства сравнений, несмотря на их недостаточную точность, и что он сужает полосу сравниваемых чисел до нескольких.

Этот алгоритм будет работать для диапазонов аргументов, превышающих десять триллионов (время расчета в несколько минут при скоростях IDEOne), когда он больше не будет корректным из-за недостаточной точности значений представления журнала в соответствии с обсуждением @ WillNess; чтобы исправить это, мы можем изменить логарифмическое представление на логарифмическое представление roll-your-own, состоящее из целого числа фиксированной длины (124 бита для примерно двойного диапазона экспоненты, хорошо для целей более ста тысяч цифр, если каждый готов ждать); это будет немного медленнее из-за небольших целочисленных операций с множественной точностью, которые медленнее, чем операции float64, но не намного медленнее, поскольку их размер ограничен (возможно, в три раза или более медленнее).

Теперь ни одна из этих реализаций Python (без использования C или Cython, PyPy или чего-либо) не является особенно быстрой, поскольку они примерно в сто раз медленнее, чем реализованные в скомпилированном языке. Для справки, вот версия на Haskell:

{-# OPTIONS_GHC -O3 #-}

import Data.Word
import Data.Bits

nextRegular :: Integer -> ( Word32, Word32, Word32 )
nextRegular target
  | target < 2                   = ( 0, 0, 0 )
  | target .&. (target - 1) == 0 = ( fromIntegral lg2hi - 1, 0, 0 )
  | target < 9                   = case target of
                                     3 -> ( 0, 1, 0 )
                                     5 -> ( 0, 0, 1 )
                                     6 -> ( 1, 1, 0 )
                                     _ -> ( 3, 0, 0 )
  | otherwise                    = match
 where
  lg3 = logBase 2 3 :: Double; lg5 = logBase 2 5 :: Double
  lg2hi = let cntplcs v cnt =
                let nv = v `shiftR` 31 in
                if nv <= 0 then
                  let cntbts x c =
                        if x <= 0 then c else
                        case c + 1 of
                          nc -> nc `seq` cntbts (x `shiftR` 1) nc in
                  cntbts (fromIntegral v :: Word32) cnt
                else case cnt + 31 of ncnt -> ncnt `seq` cntplcs nv ncnt
          in cntplcs target 0
  lg2tgt = let mant = if lg2hi <= 53 then target `shiftL` (53 - lg2hi)
                      else target `shiftR` (lg2hi - 53)
           in fromIntegral lg2hi +
                logBase 2 (fromIntegral mant / 2^53 :: Double)
  lg2top = (lg2tgt^3 + 2 * 6 * lg3 * lg5)**(1/3) -- for 2 numbers or so higher
  lg2btm = 2* lg2tgt - lg2top -- or two numbers or so lower
  match =
    let klmt = floor (lg2top / lg5)
        loopk k mtchlgk mtchtplk =
          if k > klmt then mtchtplk else
          let p = lg2top - fromIntegral k * lg5
              jlmt = fromIntegral $ floor (p / lg3)
              loopj j mtchlgj mtchtplj =
                if j > jlmt then loopk (k + 1) mtchlgj mtchtplj else
                let q = p - fromIntegral j * lg3
                    ( i, frac ) = properFraction q; r = lg2top - frac
                    ( nmtchlg, nmtchtpl ) =
                      if r < lg2btm || r >= mtchlgj then
                        ( mtchlgj, mtchtplj ) else
                      if 2^i * 3^j * 5^k >= target then
                        ( r, ( i, j, k ) ) else ( mtchlgj, mtchtplj )
                in nmtchlg `seq` nmtchtpl `seq` loopj (j + 1) nmtchlg nmtchtpl
          in loopj 0 mtchlgk mtchtplk
    in loopk 0 (fromIntegral lg2hi) ( fromIntegral lg2hi, 0, 0 )


trival :: ( Word32, Word32, Word32 ) -> Integer
trival (i,j,k) = 2^i * 3^j * 5^k

main = putStrLn $ show $ nextRegular $ (trival (1334,335,404)) + 1 -- (1126,16930,40)

Этот код вычисляет следующее обычное число, следующее за миллиардной, за слишком малое время, которое нужно измерить, и за триллионной за 0,69 секунды в IDEOne (и потенциально может работать даже быстрее, за исключением того, что IDEOne не поддерживает LLVM). Даже Джулия будет бегать с такой скоростью на Хаскеле после «разминки» для компиляции JIT.

EDIT_ADD: Код Джулии следующий:

function nextregular(target :: BigInt) :: Tuple{ UInt32, UInt32, UInt32 }
    # trivial case of first value or anything less...
    target < 2 && return ( 0, 0, 0 )

    # Check if it's already a power of 2 (or a non-integer)
    mant = target & (target - 1)

    # Quickly find next power of 2 >= target
    log2hi :: UInt32 = 0
    test = target
    while true
        next = test & 0x7FFFFFFF
        test >>>= 31; log2hi += 31
        test <= 0 && (log2hi -= leading_zeros(UInt32(next)) - 1; break)
    end

    # exit if this is a power of two already...
    mant == 0 && return ( log2hi - 1, 0, 0 )

    # take care of trivial cases...
    if target < 9
        target < 4 && return ( 0, 1, 0 )
        target < 6 && return ( 0, 0, 1 )
        target < 7 && return ( 1, 1, 0 )
        return ( 3, 0, 0 )
    end

    # find log of target, which may exceed the Float64 limit...
    if log2hi < 53 mant = target << (53 - log2hi)
    else mant = target >>> (log2hi - 53) end
    log2target = log2hi + log(2, Float64(mant) / (1 << 53))

    # log2 constants
    log2of2 = 1.0; log2of3 = log(2, 3); log2of5 = log(2, 5)

    # calculate range of log2 values close to target;
    # desired number has a logarithm of log2target <= x <= top...
    fctr = 6 * log2of3 * log2of5
    top = (log2target^3 + 2 * fctr)^(1/3) # for 2 numbers or so higher
    btm = 2 * log2target - top # or 2 numbers or so lower

    # scan for values in the given narrow range that satisfy the criteria...
    match = log2hi # Anything found will be smaller
    result :: Tuple{UInt32,UInt32,UInt32} = ( log2hi, 0, 0 ) # placeholder for eventual matches
    fives :: UInt32 = 0; fiveslmt = UInt32(ceil(top / log2of5))
    while fives < fiveslmt
        log2p = top - fives * log2of5
        threes :: UInt32 = 0; threeslmt = UInt32(ceil(log2p / log2of3))
        while threes < threeslmt
            log2q = log2p - threes * log2of3
            twos = UInt32(floor(log2q)); log2this = top - log2q + twos

            if log2this >= btm && log2this < match
                # logarithm precision may not be enough to differential between
                # the next lower regular number and the target, so do
                # a full resolution comparison to eliminate this case...
                if (big(2)^twos * big(3)^threes * big(5)^fives) >= target
                    match = log2this; result = ( twos, threes, fives )
                end
            end
            threes += 1
        end
        fives += 1
    end
    result
end
0 голосов
/ 12 февраля 2012

Знаешь что?Я положу деньги на предположение, что на самом деле «тупой» алгоритм самый быстрый.Это основано на наблюдении, что следующее регулярное число, в общем, кажется, не намного больше, чем данный ввод.Так что просто начните считать, и после каждого приращения рефакторинг и посмотрим, нашли ли вы обычный номер.Но создайте один поток обработки для каждого имеющегося у вас ядра, и для N ядер каждый поток проверяет каждое N-е число.Когда каждый поток найдет число или превысит пороговое значение степени 2, сравните результаты (оставьте лучший номер), и вы получите.

0 голосов
/ 12 февраля 2012

Вот еще одна возможность, о которой я только что подумал:

Если N имеет длину X бит, то наименьшее регулярное число R N будет в диапазоне
[2<sup>X-1</sup>, 2<sup>X</sup>]

например, если N = 257 (двоичный 100000001), тогда мы знаем R равно 1<em>xxxxxxxx</em>, если R точно не равно следующей степени 2 (512)

Чтобы сгенерировать все регулярные числа в этом диапазоне, мы можем сгенерировать нечетные регулярные числа (т.е. кратныестепеней 3 и 5) сначала, затем возьмите каждое значение и умножьте на 2 (сдвигом битов) столько раз, сколько необходимо, чтобы привести его в этот диапазон.

В Python:

from itertools import ifilter, takewhile
from Queue import PriorityQueue

def nextPowerOf2(n):
    p = max(1, n)
    while p != (p & -p):
        p += p & -p
    return p

# Generate multiples of powers of 3, 5
def oddRegulars():
    q = PriorityQueue()
    q.put(1)
    prev = None
    while not q.empty():
        n = q.get()
        if n != prev:
            prev = n
            yield n
            if n % 3 == 0:
                q.put(n // 3 * 5)
            q.put(n * 3)

# Generate regular numbers with the same number of bits as n
def regularsCloseTo(n):
    p = nextPowerOf2(n)
    numBits = len(bin(n))
    for i in takewhile(lambda x: x <= p, oddRegulars()):
        yield i << max(0, numBits - len(bin(i)))

def nextRegular(n):
    bigEnough = ifilter(lambda x: x >= n, regularsCloseTo(n))
    return min(bigEnough)
0 голосов
/ 11 февраля 2012

Я написал небольшую программу на c # для решения этой проблемы. Это не очень оптимизировано, но это начало. Это решение довольно быстрое для чисел размером до 11 цифр.

private long GetRegularNumber(long n)
{
    long result = n - 1;
    long quotient = result;

    while (quotient > 1)
    {
        result++;
        quotient = result;

        quotient = RemoveFactor(quotient, 2);
        quotient = RemoveFactor(quotient, 3);
        quotient = RemoveFactor(quotient, 5);
    }

    return result;
}

private static long RemoveFactor(long dividend, long divisor)
{
    long remainder = 0;
    long quotient = dividend;
    while (remainder == 0)
    {
        dividend = quotient;
        quotient = Math.DivRem(dividend, divisor, out remainder);
    }
    return dividend;
}
...