你可以用 C 语言这样轻松地做到这一点:
#include <stdint.h>
uint32_t a, b; // input
uint64_t val = (uint64_t)a * b;
uint32_t high = val >> 32, low = val;
让编译器生成尽可能最好的代码。现代优化器确实很擅长。手工编码的程序集通常看起来更好但性能更差。
正如 Pete Becker 所评论的,上述内容取决于类型的可用性uint32_t
and uint64_t
。如果您坚持顽固的可移植性(假设您正在DS9K
),您可以改为使用类型uint_least32_t
and uint_least64_t
or uint_fast32_t
and uint_fast64_t
在 C99 下始终可用,但您需要一个额外的掩码,如果不需要,它将被优化:
#include <stdint.h>
uint_fast32_t a, b; // input
uint_fast64_t val = (uint_fast64_t)a * b;
uint_fast32_t high = (val >> 32) & 0xFFFFFFFF, low = val & 0xFFFFFFFF;
关于除法,可以使用C99库函数div
, ldiv
or lldiv
在一次调用中执行有符号除法和余数运算。如果可能的话,在特定操作数类型的目标架构上,除法/模组合将在一次操作中实现。
编写两个表达式并依靠编译器来检测模式并生成使用单个 IDIV 操作码的代码可能会更有效:
struct divmod_t { int quo, rem; };
struct divmod_t divmod(int num, int denom) {
struct divmod_t r = { num / denom, num % denom };
return r;
}
测试于Matt Godbolt 的编译器浏览器 https://godbolt.org/g/oOvl17显示 clang 和 gcc 都生成一个idiv
该代码的说明位于-O3
.
您可以将这些除法之一转化为乘法:
struct divmod_t { int quo, rem; };
struct divmod_t divmod2(int num, int denom) {
struct divmod_t r;
r.quo = num / denom;
r.rem = num - r.quo * denom;
return r;
}
请注意,上述函数不会检查潜在的溢出,这会导致未定义的行为。如果发生溢出denom = 0
and if num = INT_MIN
and denom = -1
.