处理嵌入式C上的小数

时间:2015-08-02 23:49:57

标签: c embedded microcontroller pic floating

我的代码如下,我想问一下解决数字(除法,乘法,对数,指数)的最佳方法是什么?我使用PIC16F1789作为我的设备。

     super.viewDidLoad()
    self.commentstableView.separatorColor = UIColor.clearColor()


 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    //post's section == 0

    if indexPath.section == 0 {
        let cell = tableView.dequeueReusableCellWithIdentifier("postCID", forIndexPath: indexPath) as! postCell


         self.commentstableView.separatorColor = UIColor.grayColor()


    }

        let cell = tableView.dequeueReusableCellWithIdentifier("commentCID", forIndexPath: indexPath) as! commentCell
        // Configure the cell...
        cell.textLabel?.text = comments[indexPath.row]

        return cell



}

3 个答案:

答案 0 :(得分:3)

通常,在MCU上,浮点类型比整数类型更昂贵(时钟,代码)。虽然这对于具有硬件浮点单元的设备来说通常是正确的,但它在没有PIC16 / 18控制器的情况下成为设备上的重要信息。这些必须模拟软件中的所有浮点运算。这可以很容易地在每次添加时花费大约100个时钟周期(更多用于乘法)并且使代码膨胀。

所以,最好是避免float(在这类系统上不要说double

对于您的示例,ADC无论如何都返回一个整数类型,因此求和可以完全用整数类型完成。你只需要确保summand不会溢出,所以它必须为你的代码保持~100 *。

最后,要计算平均值,您可以将整数除以迭代次数(舍入为零),或者 - 更好 - 通过以下方法应用简单的“舍入到最近”:

#define NUMBER_OF_ITERATIONS 100

sensorAverage = (sensorValue + NUMBER_OF_ITERATIONS / 2) / NUMBER_OF_ITERATIONS;

如果您真的想加速代码,请将NUMBER_OF_ITERATIONS设置为2的幂(此处为64或128),如果您的代码可以容忍这一点。

最后:要获得除法的整数部分,您可以将总和(sensoreValue)视为小数值。对于给定的100次迭代,您可以将其视为小数:当转换为字符串时,只需打印较低2位数左侧的小数点。当你除以100时,小数部分的数字不会超过两个。如果你真的需要4个数字,例如对于其他操作,你可以将总和乘以 100(实际上,它是10000,但你已经通过循环将它乘以100)。

这称为十进制定点。处理速度更快(用移位替换乘法)将使用二进制固定点,如上所述。

在PIC16上,我强烈建议考虑使用二进制分数作为乘法和除法在这个平台上非常昂贵。通常,它们不适合信号处理。如果你需要保持一些性能,ARM Cortex-M0或M4将是更好的选择 - 价格相近。

答案 1 :(得分:3)

在您的示例中,完全避免非整数表示是微不足道的,但是为了更一般地回答您的问题,ISO兼容编译器将支持浮点运算和库,但出于性能和代码大小的原因,您可能希望避免这种情况

定点算术是你可能需要的。对于简单的计算,可以使用特定的固定点方法,例如,您将示例中sensorAverage的单位视为百分之一(1/100),并完全避免昂贵的划分。但是,如果要执行完整的数学库操作,则更好的方法是使用定点库。安东尼·威廉姆斯在Optimizing Applications with Fixed-Point Arithmetic中提出了一个这样的图书馆。代码是C ++,PIC16可能缺少一个不错的C ++编译器,但这些方法可以在不太优雅的情况下移植到C.它还使用了一个巨大的64位定点36Q28格式,这对PIC16来说既昂贵又慢;您可能希望将其改编为使用16Q16。

答案 2 :(得分:0)

如果你真的关心性能,坚持使用整数算术,尝试使样本数平均为2的幂,这样可以通过位移来进行除法,但是如果它不是2的幂让我们说100(因为奥拉夫指出固定点)你也可以使用位移和添加:How can I multiply and divide using only bit shifting and adding?

如果您不关心性能并且仍然希望使用浮点数(您已经收到警告,这可能在PIC16中可能不是很快并且可能使用大量闪存),math.h具有以下功能:{{ 3}}包括exponeciation:pow(base,exp)和logarithms *只有base 2,base 10和base e,对于任意基数使用基数对数属性的变化