Вы можете сначала разделить a на c, а также получить напоминание о делении и умножить напоминание на b, а затем разделить его на c. Таким образом, вы потеряете данные только в последнем делении и получите тот же результат, что и при делении на 64 бита.
Вы можете переписать формулу следующим образом (где \ - целочисленное деление):
a * b / c =
(a / c) * b =
(a \ c + (a % c) / c) * b =
(a \ c) * b + ((a % c) * b) / c
Убедившись, что a> = b, вы можете использовать большие значения перед их переполнением:
uint32_t muldiv(uint32_t a, uint32_t b, uint32_t c) {
uint32_t hi = a > b ? a : b;
uint32_t lo = a > b ? b : a;
return (hi / c) * lo + (hi % c) * lo / c;
}
Другой подход заключается в циклическом сложении и вычитании вместо умножения и деления, но это, конечно, лот дополнительная работа:
uint32_t muldiv(uint32_t a, uint32_t b, uint32_t c) {
uint32_t hi = a > b ? a : b;
uint32_t lo = a > b ? b : a;
uint32_t sum = 0;
uint32_t cnt = 0;
for (uint32_t i = 0; i < hi; i++) {
sum += lo;
while (sum >= c) {
sum -= c;
cnt++;
}
}
return cnt;
}