Походит каждый раз, когда я делю отрицательный интервал на положительный интервал, мне нужен он для округления в меньшую сторону (к-inf), не к 0. Но и C# и C++ вокруг к 0.
Таким образом, я предполагаю, что мне нужен DivideDownward () метод. Я могу записать это в нескольких строках с тестом для отрицания и так далее, но мои идеи кажутся klugey. Таким образом, я задаюсь вопросом, пропускаю ли я что-то и если у Вас есть "изящный" путь к круглому отрицательному подразделению вниз.
ВНИМАНИЕ: это сообщение дает неверные результаты для ввода с 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 ».
Каждый раз, когда я делю отрицательное int на положительное int, мне нужно округлить в меньшую сторону .
Это же ад, не так ли? Кнут написал, почему это правильный способ делать что-то, но мы застряли на устаревшем целочисленном оборудовании.
Если вы можете позволить себе потерю точности, самый простой и понятный способ сделать это - преобразовать 32-битное целое число в 64-битное двойное
и использовать режим округления FP для округления в сторону минуса. бесконечность, когда вы конвертируете частное обратно в целое число. Сегодняшние единицы с плавающей запятой довольно быстрые и могут фактически делить быстрее , чем целочисленные единицы; чтобы быть уверенным, вам придется измерить.
Если вам нужна полная 64-битная целочисленная точность, я, как писатель компилятора, решил эту проблему, выполнив две условные ветви, так что вы в конечном итоге делите величины, а затем получаете правильный знак. Но это было некоторое время назад, когда условная ветвь была дешевой по сравнению с разделением; на сегодняшнем оборудовании мне пришлось бы поэкспериментировать, прежде чем я смогу что-то порекомендовать.
В принципе, вы можете использовать уловку с плавающей запятой на 64-битных int, используя устаревшие 80-битные числа с плавающей запятой Intel, но это совершенно непереносимо, и я не верю, что Intel будет продолжать делать это устройство быстро. . В наши дни скорость с плавающей запятой выражается в единицах SSE.
Среди других уловок можно найти книгу Хэнка Уоррена Hacker's Delight (моя копия находится в работе) и компилятор MLton для Standard ML, который требует округления до целочисленного деления. минус бесконечность.
Что бы вы ни делали, когда вы определитесь с этим, если вы используете C ++ или C99, вставьте свою процедуру разделения в файл .h и сделайте его статическим встроенным
. Таким образом, когда ваше решение окажется неоптимальным для нового оборудования Whizbang, поставленного через 5 лет, у вас будет одно место, где его можно изменить.
Math.Floor((double)a/(double)b)
если вам нужно как int, приведите его после этого
(int)Math.Floor((double)a/(double)b)
Если вы хотите написать это, просто используя целые числа в относительно сжатой форме, вы можете написать следующее:
var res = a / b - (a % b < 0 ? 1 : 0);
Это, вероятно, компилируется в довольно много инструкций, но все же может быть быстрее, чем использование чисел с плавающей запятой.