在C中执行这些乘法的最佳方法是什么

在C中执行这些乘法的最佳方法是什么,c,C,我用MAXIM的这个函数为电能表设计提供了一个示例代码,它可以执行这个计算 E = W * 6.6972*10^-13 * VMAX * IMAX (Wh) VMAX = 600 (but it is stored in the code with a resolution of 0.1 making it 6000) IMAX = 208 (also stored as 2080) 这是瓦特乌尔的能量 W是能量芯片测量的千瓦时原始值。根据能量芯片(第77页)中提供的上述等式,计算将其转换为

我用MAXIM的这个函数为电能表设计提供了一个示例代码,它可以执行这个计算

E = W * 6.6972*10^-13 * VMAX * IMAX (Wh)

VMAX = 600 (but it is stored in the code with a resolution of 0.1 making it 6000)
IMAX = 208 (also stored as 2080)
这是瓦特乌尔的能量

W是能量芯片测量的千瓦时原始值。根据能量芯片(第77页)中提供的上述等式,计算将其转换为瓦特胡尔,并将其作为有符号32位整数返回

这是密码

#define ONE_MILLION (1000000L)
#WATTSCALE 1885L        // 6.6972E-12 * 2^48.

 static U32 Whr (U08x *w)
{                                             // 'w' is a 8-byte quantity.

U08 xdata x[13], y[12];                  // Need extra digit for divide.
    U32 xdata scale;
    U08 xdata t[4+4+1];

    scale = (U32) Vmax * (U32) Imax;          //scale=[Vmax*10E+01] * [Imax*10E+01].
    multiply_8_4 (y, w,(U08x *)&scale);       // y = w * Vmax * Imax * 10E+02.
    scale = WATTSCALE;                        //[LSB * 2^48 * 10E+01]  (10E-03 Wh).
    multiply_8_4 (x + 1, y,(U08x *)&scale);   //[x*2^16] = [y/2^32]*[LSB * 2^48] (mWh)
                                              //..dropped low-order 4-bytes of 'y'.
    scale = ONE_MILLION;                      // Modulo ONE_MILLION.
    divide (x + 1, (U08x *) &scale, 10, 4, t);// x / 1,000,000;
    x[7] = 0;                                 //Clear high order of 4-byte result.
    return (* (U32x *) &x[7]);                // Return 32-bit answer (x % 1,000,000). 
}
multiply_8_4()是一个函数,它将一个8字节的数据(这是w指向的数据)乘以一个4字节的数据(比例),并将结果放入另一个缓冲区(在本例中为缓冲区x)

我只是想知道,为什么简单的计算(在我看来)会以2^48和2^32的乘法和除法这样复杂


除了程序员的选择之外,还有什么特别的原因吗?

看起来他们使用的是一个8位微控制器,它不进行浮点计算。他们还指出,从内存中提取数据时,以字节为单位,而不是以短字符或整数为单位,效率更高。您所展示的代码实现了定点乘法,其中常量和值经过缩放,以在二进制点的两侧提供足够的空间,从而不会发生溢出,并有足够的精度满足其需要。

出于某种原因,程序员选择/不得不在整数上而不是在整数上进行计算浮点值。因此:

  • 他不能对低于1的有效位数过多的值进行操作。如果尝试将6.6972*10^-13存储为整数,则会得到0。所以,6.6972*10^-13乘以2^48得到1885.094214。。。在圆点后剪切数字可能没问题

  • 不是


  • 但这不是一个简单的整数计算。据猜测,浮动被认为太不准确而没有用处。不管这是真是假,我都不知道,但这肯定是完全可能的。你能一步一步地检查代码或记录结果,这样你就可以准确地确定你在哪里得到了错误的值吗?@Jay我没有得到任何错误的值,计算是正确的,我已经一步一步地完成了。我只是想了解他们为什么要费尽心机来进行计算,如果他们的方法真的有好处的话,我觉得非常复杂,汉克,有一个2^48的乘法,还有一个2^32的除法(尽管我还没有弄清楚除法是在哪里发生的),这使得2^16仍处于混合状态。我也不知道2^16是如何从最终结果中删除的。你也能帮我吗?好吧,坦白地说,第二次看,这里没有2^32的除法和2^16的乘法。评论有时是谎言。放弃我答案中的第2点。请注意,divide()的结果被写入地址
    x+1
    ,因此
    (U32x*)x[7]
    意味着“将
    x+1的值移位6个字节。6*8=48,这样就可以了:
    返回(*(U32x*)&x[7]);
    行中的值被2^48“除”。第二次乘法中真正发生的是
    [x+1]=[y]*[LSB*2^48](兆瓦时)