Как найти следующий кратный 10 из любого целого?
Динамическое целое число будет любым числом от 0 до 150.
то есть. - возвращает число 41, нужно вернуть 50. Если число равно 10, нужно возвратить 10. Число 1 нужно вернуть 10.
Думал, что могу использовать функцию потолка, если я изменяю целое число как десятичное...? затем используйте функцию потолка и верните ее в десятичную точку?
Остается только знать, является ли число 1, 2 или 3 цифры (то есть - 7 против 94 против 136)
Есть ли лучший способ достичь этого?
Спасибо,
Ответы
Ответ 1
n + (10 - n % 10)
Как это работает. Оператор% вычисляет остальную часть деления (поэтому 41 % 10
оценивается до 1, а 45 % 10
оценивается до 5). Вычитая, что из 10 оценивает, сколько вам нужно, чтобы достигнуть следующего кратного.
Единственная проблема заключается в том, что это превратится в 40 в 50. Если вы этого не хотите, вам нужно будет добавить проверку, чтобы убедиться, что она уже не кратна 10.
if (n % 10)
n = n + (10 - n % 10);
Ответ 2
Вы можете сделать это, выполнив целочисленное деление на 10 округление, а затем умножив результат на 10.
Чтобы разделить A
на B
округление, добавьте B - 1
в A
, а затем разделите его на B
с помощью "обычного" целочисленного деления
Q = (A + B - 1) / B
Итак, для вашей конкретной проблемы все вместе будет выглядеть следующим образом
A = (A + 9) / 10 * 10
Это будет "привязать" A
к следующему большему краю 10.
Необходимость разделения и для выравнивания возникает настолько часто, что обычно в моих программах у меня бы были макросы для деления целых чисел без знака с округлением
#define UDIV_UP(a, b) (((a) + (b) - 1) / (b))
и для выравнивания целого числа с следующей границей
#define ALIGN_UP(a, b) (UDIV_UP(a, b) * (b))
который сделал бы это выше, как
A = ALIGN_UP(A, 10);
P.S. Я не знаю, нужно ли вам это расширить до отрицательных чисел. Если вы это сделаете, следует позаботиться о том, чтобы сделать это правильно, в зависимости от того, что вам нужно в результате.
Ответ 3
Как насчет ((n + 9) / 10) * 10
?
Выход 0 = > 0, 1 = > 10, 8 = > 10, 29 = > 30, 30 = > 30, 31 = > 40
Ответ 4
Как насчет использования целочисленной математики:
N=41
N+=9 // Add 9 first to ensure rounding.
N/=10 // Drops the ones place
N*=10 // Puts the ones place back with a zero
Ответ 5
tl; dr: ((n + 9) / 10) * 10
компилируется в самый лучший (самый быстрый) код asm в большинстве случаев, и его легко читать и понимать для людей, которые знают, что такое целочисленное деление на C. Это довольно распространенная идиома.
Я не исследовал, какой лучший вариант для чего-то, что должно работать с отрицательным n
, так как вы можете захотеть округлить от нуля, а не оставаться в направлении + бесконечности, в зависимости от приложения.
Глядя на операции C, используемые различными предложениями, самым легким является Марк Дикинсон (в комментариях):
(n+9) - ((n+9)%10)
Он выглядит более эффективным, чем простое разделение/умножение, предложенное несколькими людьми (в том числе @bta): ((n + 9) / 10) * 10
, потому что у него просто есть добавление, а не умножение. (n+9
- общее подвыражение, которое нужно вычислять только один раз.)
Оказывается, что оба компилируются в буквально идентичный код, используя трюк компилятора преобразования деления на константу в умножить и сдвинуть, см. этот Q & A для того, как он работает. В отличие от аппаратной команды div
, которая стоит того же, независимо от того, используете ли вы результат quotient, остаток или оба результата, метод mul/shift делает дополнительные шаги для получения остатка. Таким образом, компилятор видит, что он может получить тот же результат от более дешевого вычисления и заканчивает компиляцию обеих функций в один и тот же код.
Это верно для x86, ppc и ARM, а также для всех других архитектур, которые я просмотрел в проводнике компилятора Godbolt. В первой версии этого ответа я увидел sdiv
для %10
для Godbolt gcc4.8 для ARM64, но он больше не установлен (возможно, потому, что он был неправильно сконфигурирован?) ARM64 gcc5.4 этого не делает.
В Godbolt установлен MSVC (CL), и некоторые из этих функций компилируются по-разному, но я не нашел времени, чтобы лучше понять, какая компиляция.
Обратите внимание, что в выводе gcc для x86 умножить на 10 выполняется дешево с lea eax, [rdx + rdx*4]
, чтобы сделать n * 5, затем add eax,eax
, чтобы удвоить это. imul eax, edx, 10
будет иметь задержку на 1 цикл выше на Intel Haswell, но будет короче (на один уровень меньше). gcc/clang не используют его даже с -Os -mtune=haswell
:/
Принятый ответ (n + 10 - n % 10
) еще дешевле вычислять: n+10
может происходить параллельно с n%10
, поэтому цепочка зависимостей на один шаг короче. Он компилируется с меньшим количеством инструкций.
Однако он дает неправильный ответ для кратных 10: например. 10 -> 20
. В предлагаемом исправлении используется if(n%10)
, чтобы решить, что делать. Это скомпилируется в cmov
, поэтому он дольше и хуже, чем @Bta-код. Если вы собираетесь использовать условное выражение, сделайте это, чтобы получить нормальные результаты для отрицательных входов.
Здесь описываются все предлагаемые ответы, в том числе для отрицательных входов:
./a.out | awk -v fmt='\t%4s' '{ for(i=1;i<=NF;i++){ a[i]=a[i] sprintf(fmt, $i); } } END { for (i in a) print a[i]; }'
i -22 -21 -20 -19 -18 -12 -11 -10 -9 -8 -2 -1 0 1 2 8 9 10 11 12 18 19 20 21 22
mark -10 -10 -10 -10 0 0 0 0 0 0 0 0 0 10 10 10 10 10 20 20 20 20 20 30 30
igna -10 -10 -10 0 0 0 0 0 10 10 10 10 10 10 10 10 10 20 20 20 20 20 30 30 30
utaal -20 -20 -20 -10 -10 -10 -10 -10 0 0 0 0 0 10 10 10 10 10 20 20 20 20 20 30 30
bta -10 -10 -10 -10 0 0 0 0 0 10 10 10 10 10 10 10 10 10 20 20 20 20 20 30 30
klatchko -10 -10 -10 -10 0 0 0 0 0 0 0 0 0 10 10 10 10 10 20 20 20 20 20 30 30
branch -10 -10 -20 0 0 0 0 -10 10 10 10 10 0 10 10 10 10 10 20 20 20 20 20 30 30
(транспонировать awk-программу)
Ignacio n + (((9 - (n % 10)) + 1) % 10)
работает "правильно" для отрицательных целых чисел, округляя до + бесконечности, но намного дороже вычислять. Он требует двух модульных операций, поэтому он по существу вдвое дороже. Он компилирует примерно в два раза больше инструкций x86, делая примерно в два раза больше работы других выражений.
Программа для печати результатов (такая же, как ссылки на боксбол)
#include <stdio.h>
#include <stdlib.h>
int f_mark(int n) { return (n+9) - ((n+9)%10); } // good
int f_bta(int n) { return ((n + 9) / 10) * 10; } // compiles to literally identical code
int f_klatchko(int n) { return n + 10 - n % 10; } // wrong, needs a branch to avoid changing multiples of 10
int f_ignacio(int n) { return n + (((9 - (n % 10)) + 1) % 10); } // slow, but works for negative
int roundup10_utaal(int n) { return ((n - 1) / 10 + 1) * 10; }
int f_branch(int n) { if (n % 10) n += (10 - n % 10); return n; } // gcc uses cmov after f_accepted code
int main(int argc, char**argv)
{
puts("i\tmark\tigna\tutaal\tbta\tklatch\tbranch");
for (int i=-25 ; i<25 ; i++)
if (abs(i%10) <= 2 || 10 - abs(i%10) <= 2) // only sample near interesting points
printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\n", i, f_mark(i), f_accepted(i),
f_ignacio(i), roundup10_utaal(i), f_bta(i), f_branch(i));
}
Ответ 6
в C, однострочный:
int inline roundup10(int n) {
return ((n - 1) / 10 + 1) * 10;
}
Ответ 7
Помните, что ответы, основанные на операторах div и mod ( "/" и "%" ), не будут работать для отрицательных чисел без if-теста, потому что C и С++ неправильно реализуют эти операторы для отрицательных чисел. (-3 mod 5) равно 2, но C и С++ вычисляют (-3% 5) как -3.
Вы можете определить свои собственные функции div и mod. Например,
int mod(int x, int y) {
// Assert y > 0
int ret = x % y;
if(ret < 0) {
ret += y;
}
return ret;
}
Ответ 8
Вы можете сделать число mod 10. Затем возьмите этот результат, вычтите его из десяти. Затем добавьте этот результат в оригинал.
if N%10 != 0 #added to account for multiples of ten
a=N%10
N+=10-a
Ответ 9
n + (((9 - (n % 10)) + 1) % 10)
Ответ 10
int n,res;
...
res = n%10 ? n+10-(n%10) : n;
или
res = (n / 10)*10 + ((n % 10) ? 10:0);
Ответ 11
В псевдокоде:
number = number / 10
number = ceil(number)
number = number * 10
В Python:
import math
def my_func(x):
return math.ceil(x / 10) * 10
Это должно сделать это. Имейте в виду, что вышеприведенный код будет отличать целое число с float/double для арифметики, и его можно вернуть обратно к целому числу для окончательного возврата. Вот пример с явным приведением типов
В Python (с приведением типов):
import math
def my_func(x):
return int(math.ceil(float(x) / 10) * 10)
Ответ 12
round_up(int i)
{
while(i%10) {
i++;
}
return(i);
}