我遇到了C语言的算术运算问题:“该部门”。 问题并非如此简单,因为嵌入式系统支持不超过32位的操作。所以,我不能对64位应用任何算术运算(这就是我需要的)。 要解决此问题,我使用的是Union / Struct:
typedef union {
long long n64;
struct {
unsigned int low;
unsigned int high;
} n32;
} My64;
我已经用C ++实现了这个并调整为C语言:
long long div_s64s64_s64(long long A, long long B)
{
My64 myA, myB, myBn, myQ, myR;
int i;
unsigned char negative = 0;
myA.n64 = A;
myB.n64 = B;
if (myB.n32.high == 0 && myB.n32.low == 0)
{
return 0xffffffffffffffff;
}
if (myA.n32.high & (1 << 31))
{
negative = 1;
//2 complement
myA.n32.low = ~myA.n32.low;
myA.n32.high = ~myA.n32.high;
myA.n64 = add(myA.n64, 1);
}
if (myB.n32.high & (1 << 31))
{
negative = !negative;
//2 complement
myB.n32.low = ~myB.n32.low;
myB.n32.high = ~myB.n32.high;
myB.n64 = add(myB.n64, 1);
}
//Bn = -B (2 complement)
myBn.n32.low = ~myB.n32.low;
myBn.n32.high = ~myB.n32.high;
myBn.n64 = add(myBn.n64, 1);
//Quocient
myQ.n64 = 0;
//Rest
myR.n64 = 0;
for (i = 63; i >= 0; i--)
{
//R = R << 1
myR.n32.high = (myR.n32.high << 1) | ((myR.n32.low >> 31) & 1);
myR.n32.low = myR.n32.low << 1;
//R(0) := N(i), bit 0 of R becomes bit i of N
myR.n32.low = myR.n32.low | ((i >= 32 ? myA.n32.high >> (i - 32) : myA.n32.low >> i) & 1);
//if R ≥ D then
if (myR.n32.high > myB.n32.high || (myR.n32.high == myB.n32.high && myR.n32.low > myB.n32.low) || (myR.n32.high == myB.n32.high && myR.n32.low == myB.n32.low))
{
//R := R − D
myR.n64 = add(myR.n64, myBn.n64);
//Q(i) := 1, bit i of Q becomes 1
if (i >= 32)
{
myQ.n32.high = myQ.n32.high | (1 << (i - 32));
}
else
{
myQ.n32.low = myQ.n32.low | (1 << i);
}
}
}
if (negative)
{
//2 complement
myQ.n32.low = ~myQ.n32.low;
myQ.n32.high = ~myQ.n32.high;
myQ.n64 = add(myQ.n64, 1);
}
return myQ.n64;
}
如果 B = 0 ,该函数返回2 ^ 64-1。没问题!否则,返回1,有时返回-1。错!
预期: 100/2 = 50 实际: 100/2 = 1
你能帮我解决这个问题吗?
致以最诚挚的问候,
答案 0 :(得分:0)
当然,您的编译器具有64位除法的运行时库实现。一定。只需使用标准C(uint64_t/int64_t/long long
等)进行数学运算,编译器将通过调用它们提供的库函数来填充其余部分。
这将是正确的,并且(可能)比你能写的任何东西都更有效率。
除非你问这个,因为它是一个家庭作业。如果是这种情况,请查看您的教科书,不要问我们。
答案 1 :(得分:-1)
显然有一个等效函数in the Linux kernel(故意与较旧版本相关联;较新版本似乎更复杂)。
也许你可以用它作为灵感? (请不要复制粘贴,除非您也愿意根据GPL许可您的代码。)