Nano Hash - криптовалюты, майнинг, программирование

Когда полезна разница между quotRem и divMod?

Из отчета Haskell:

Методы класса quot, rem, div и mod удовлетворяют этим законам, если y не равен нулю:

(x `quot` y)*y + (x `rem` y) == x
(x `div`  y)*y + (x `mod` y) == x

quot представляет собой целочисленное деление, усеченное в сторону нуля, а результат div усекается в сторону отрицательной бесконечности.

Например:

Prelude> (-12) `quot` 5
-2
Prelude> (-12) `div` 5
-3

Каковы некоторые примеры того, где разница между тем, как усекается результат, имеет значение?

04.12.2008

Ответы:


1

Во многих языках есть оператор «mod» или «%», который дает остаток после деления с усечением до 0; например, C, C++ и Java и, возможно, C# сказали бы:

(-11)/5 = -2
(-11)%5 = -1
5*((-11)/5) + (-11)%5 = 5*(-2) + (-1) = -11.

quot и rem в Haskell предназначены для имитации такого поведения. Я могу себе представить, что совместимость с выводом какой-нибудь программы на языке C может быть желательной в какой-то надуманной ситуации.

div и mod в Haskell, а впоследствии / и % в Python, следуют соглашению математиков (по крайней мере, теоретиков чисел) всегда усекать деление вниз (не в сторону 0 — в сторону отрицательной бесконечности), так что остаток всегда неотрицательна. Таким образом, в Python

(-11)/5 = -3
(-11)%5 = 4
5*((-11)/5) + (-11)%5 = 5*(-3) + 4 = -11.

Haskell div и mod следуют этому поведению.

04.12.2008
  • так что остаток всегда неотрицательный. Технически знак mod следует за знаком второго операнда. 07.05.2009
  • это для поддержания свойства, что (q,r) = divMod x y тогда и только тогда, когда x = q*y + r. Запустите пример, это умно, как это работает. 17.12.2010
  • @luqui: Нет, это не объясняет. Вы всегда можете иметь x=q*y+r с неотрицательным r; например если divMod 11 (-5) = (-2, 1) (вместо (-3,-4)), у вас все равно будет 11 = (-2)*(-5) + 1. Таким образом, ваше условие не заставляет знак mod следовать за вторым операндом. Кстати, свойство x=q*y+r всегда верно и для quotRem, и всегда существует бесконечно много пар (q,r) таких, что x=q*y+r (и ровно две из этих пар имеют |r|‹q, за исключением случаев, когда r=0 дает решение есть только одна пара). 17.12.2010
  • Хм, да. Может быть, mod компенсирует какое-то связанное дизайнерское решение в div? Точно сказать не могу... 17.12.2010
  • На самом деле, в то время как C99 и C++11 определяют определение усечения до 0, более ранние версии оставляли его определяемым реализацией, поэтому совместимость с C является маловероятной (или, по крайней мере, плохой…) причиной для других языков или программ. усечение до 0. 29.08.2013

  • 2

    Это не совсем ответ на ваш вопрос, но в GHC на x86 quotRem на Int будет компилироваться в одну машинную инструкцию, тогда как divMod выполняет немного больше работы. Так что, если вы находитесь в разделе, критичном для скорости, и работаете только с положительными числами, quotRem — это то, что вам нужно.

    04.12.2008
  • Для решения простых чисел SPOJ использование rem, а не mod заставляет мой тестовый файл работать за 4,758 с, а не 5,533 с. Это означает, что более быстрая версия работает на 16% быстрее в 32-разрядной версии Ubuntu, Haskell Platform 2011. 05.05.2011
  • @TimPerry, я не думаю, что это следует. Что, если бы вы сделали одно mod во всей программе и увидели такое же улучшение? 11.01.2013
  • Я заявил, что когда я изменил вызовы в моем коде простых чисел с mod на rem, я увидел ускорение на 20%. Это не теоретический комментарий. Это было описание события. Я изменил только одну вещь (хотя и в нескольких местах) и увидел ускорение на 20%. Кажется, следует 20%-ное ускорение DID. 12.01.2013
  • @TimPerry ах, я думал, что более быстрая версия относится к rem, а не к вашей модифицированной программе. (Хотя не знаю, почему я думал, что вы просто не скажете rem, если это то, что вы имели в виду...) 12.01.2013
  • Во многих архитектурах, включая x86, при делении на неконстанты использование усечения в сторону нуля немного быстрее, чем деление на пол в сторону отрицательной бесконечности, но при делении на множество постоянных значений, особенно на степени двойки, усечение в сторону нуля ноль намного быстрее (например, одна инструкция против 3). Я бы сказал, что код, чувствительный к скорости, может иметь больше быстрых делений, чем медленных. 14.11.2013

  • 3

    Простой пример, когда это имеет значение, — это проверка того, является ли целое число четным или нечетным.

    let buggyOdd x = x `rem` 2 == 1
    buggyOdd 1 // True
    buggyOdd (-1) // False (wrong!)
    
    let odd x = x `mod` 2 == 1
    odd 1 // True
    odd (-1) // True
    

    Заметьте, конечно, что вы могли бы не думать об этих проблемах, просто определив нечетное таким образом:

    let odd x = x `rem` 2 /= 0
    odd 1 // True
    odd (-1) // True
    

    В общем, просто помните, что для y > 0 x mod y всегда возвращает что-то >= 0, а x rem y возвращает 0 или что-то того же знака, что и x.

    04.12.2008
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..