Как разделить целое число круглые отрицательные числа *вниз*?

Походит каждый раз, когда я делю отрицательный интервал на положительный интервал, мне нужен он для округления в меньшую сторону (к-inf), не к 0. Но и C# и C++ вокруг к 0.

Таким образом, я предполагаю, что мне нужен DivideDownward () метод. Я могу записать это в нескольких строках с тестом для отрицания и так далее, но мои идеи кажутся klugey. Таким образом, я задаюсь вопросом, пропускаю ли я что-то и если у Вас есть "изящный" путь к круглому отрицательному подразделению вниз.

20
задан Conrad Albrecht 15 June 2010 в 00:58
поделиться

4 ответа

ВНИМАНИЕ: это сообщение дает неверные результаты для ввода с a = -1. Пожалуйста, посмотрите другие ответы. -Камера


[c ++]

Вероятно, это то, что вы имели в виду под «kludgey», но это то, что я придумал;)

int divideDown(int a, int b){
    int r=a/b;
    if (r<0 && r*b!=a)
        return r-1;
    return r;
}

В операторе if я поставил r <0 - однако я не уверен, что это то, что ты хочешь.Вы можете изменить оператор if на

if (a<0 && b>0)

, который будет соответствовать вашему описанию: «Похоже, когда я делю отрицательное int на положительное int ».

5
ответ дан 29 November 2019 в 23:27
поделиться

Каждый раз, когда я делю отрицательное int на положительное int, мне нужно округлить в меньшую сторону .

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

  • Если вы можете позволить себе потерю точности, самый простой и понятный способ сделать это - преобразовать 32-битное целое число в 64-битное двойное и использовать режим округления FP для округления в сторону минуса. бесконечность, когда вы конвертируете частное обратно в целое число. Сегодняшние единицы с плавающей запятой довольно быстрые и могут фактически делить быстрее , чем целочисленные единицы; чтобы быть уверенным, вам придется измерить.

  • Если вам нужна полная 64-битная целочисленная точность, я, как писатель компилятора, решил эту проблему, выполнив две условные ветви, так что вы в конечном итоге делите величины, а затем получаете правильный знак. Но это было некоторое время назад, когда условная ветвь была дешевой по сравнению с разделением; на сегодняшнем оборудовании мне пришлось бы поэкспериментировать, прежде чем я смогу что-то порекомендовать.

  • В принципе, вы можете использовать уловку с плавающей запятой на 64-битных int, используя устаревшие 80-битные числа с плавающей запятой Intel, но это совершенно непереносимо, и я не верю, что Intel будет продолжать делать это устройство быстро. . В наши дни скорость с плавающей запятой выражается в единицах SSE.

  • Среди других уловок можно найти книгу Хэнка Уоррена Hacker's Delight (моя копия находится в работе) и компилятор MLton для Standard ML, который требует округления до целочисленного деления. минус бесконечность.

Что бы вы ни делали, когда вы определитесь с этим, если вы используете C ++ или C99, вставьте свою процедуру разделения в файл .h и сделайте его статическим встроенным . Таким образом, когда ваше решение окажется неоптимальным для нового оборудования Whizbang, поставленного через 5 лет, у вас будет одно место, где его можно изменить.

11
ответ дан 29 November 2019 в 23:27
поделиться

Math.Floor((double)a/(double)b)
если вам нужно как int, приведите его после этого
(int)Math.Floor((double)a/(double)b)

3
ответ дан 29 November 2019 в 23:27
поделиться

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

var res = a / b - (a % b < 0 ? 1 : 0);

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

6
ответ дан 29 November 2019 в 23:27
поделиться
Другие вопросы по тегам:

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