在32位嵌入式系统上使用64位进行除法运算

时间:2017-03-02 15:25:44

标签: c math embedded

我遇到了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

你能帮我解决这个问题吗?

致以最诚挚的问候,

2 个答案:

答案 0 :(得分:0)

当然,您的编译器具有64位除法的运行时库实现。一定。只需使用标准C(uint64_t/int64_t/long long等)进行数学运算,编译器将通过调用它们提供的库函数来填充其余部分。

这将是正确的,并且(可能)比你能写的任何东西都更有效率。

除非你问这个,因为它是一个家庭作业。如果是这种情况,请查看您的教科书,不要问我们。

答案 1 :(得分:-1)

显然有一个等效函数in the Linux kernel(故意与较旧版本相关联;较新版本似乎更复杂)。

也许你可以用它作为灵感? (请不要复制粘贴,除非您也愿意根据GPL许可您的代码。)