Целочисленное деление стиля Python и модуль в C

Есть два разных способа сделать это.

  1. Простой способ:

    cmap <esc>q %s/%%ARTICLE_DATE/<C-r>*/c
    

    Это не использует какие-то причудливые трюки. Он просто использует клавишу <C-r> для вставки содержимого регистра.

  2. Надежный способ:

    cmap <expr> <esc>q "%s/\V%%ARTICLE_DATE/".escape(getreg("*"), "\\/")."/c"
    

    Это использует отображение "expr", что означает, что он будет оценивать vimscript в строку и запускать эту строку как отображение. Это имеет некоторые дополнительные возможности, чтобы убедиться, что если в вашем регистре есть косая черта (вперед или назад), это не испортит поиск.

24
задан user102008 6 May 2009 в 05:02
поделиться

3 ответа

Направление округления с целочисленным делением со знаком не указано в старых стандартах C. Однако в C99 указано округление до нуля.

Вот переносимый код, который работает со всеми версиями стандартов C и архитектур ЦП:

int py_div(int a, int b)
{
  if (a < 0)
    if (b < 0)
      return -a / -b;
    else
      return -(-a / b) - (-a % b != 0 ? 1 : 0);
  else if (b < 0)
      return -(a / -b) - (a % -b != 0 ? 1 : 0);
    else
      return a / b;
}

int py_mod(int a, int b)
{
  if (a < 0)
    if (b < 0)
      return -(-a % -b);
    else
      return -a % b - (-a % -b != 0 ? 1 : 0);
  else if (b < 0)
      return -(a % -b) + (-a % -b != 0 ? 1 : 0);
    else
      return a % b;
}

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

Вы также можете захотеть взглянуть на этот тесно связанный вопрос: Округление целочисленного деления с отрицательными числами в C ++ .

13
ответ дан 29 November 2019 в 00:21
поделиться

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

r = n % a;
if (r < 0) r += a;

Очевидно, это для положительного a. Для отрицательного значения a вам необходимо:

r = n % a;
if (r > 0) r += a;

, которое (возможно, немного сбивающее с толку) объединяет, чтобы дать следующее (в C ++. В C сделать то же самое с int, а затем утомительно написать дубликат для долго-долго):

template<typename T> T sign(T t) { return t > T(0) ? T(1) : T(-1); }

template<typename T> T py_mod(T n, T a) {
    T r = n % a;
    if (r * sign(a) < T(0)) r += a;
    return r;
}

Мы можем используйте двузначную функцию знака «cheapskate», потому что мы уже знаем! = 0, иначе% будет неопределенным.

Применяя тот же принцип к делению (посмотрите на результат, а не на вход):

q = n / a;
// assuming round-toward-zero
if ((q < 0) && (q * a != n)) --q;

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

[Редактировать: могут быть некоторые крайние случаи, когда это идет не так, например, если частное или остаток INT_MAX или INT_MIN. Но в любом случае подражание математике Python для больших значений - это совсем другой вопрос; -)]

[Другое редактирование: не написана ли стандартная реализация Python на C? Вы можете тралить источник за то, что они делают]

6
ответ дан 29 November 2019 в 00:21
поделиться

Он углубляется в уродливый мир поплавков, но они дают правильные ответы на Java:

public static int pythonDiv(int a, int b) {
    if (!((a < 0) ^ (b < 0))) {
        return a / b;
    }
    return (int)(Math.floor((double)a/(double)b));
}

public static int pythonMod(int a, int b) {
    return a - b * pythonDiv(a,b);
}

Я не утверждаю об их эффективности.

-1
ответ дан 29 November 2019 в 00:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: