避开浮点数——伪浮点数

本文讨论了在定点处理器上避免使用浮点数的原因,提出了使用伪浮点数的概念,即用分数形式和位移运算来近似浮点运算。通过二进制换算和定制的加法、减法、乘法和除法运算,可以在一定程度上减少浮点运算带来的性能和大小代价,并介绍了如何确定误差和优化算法以满足系统需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于定点处理器来说,浮点数学运算的代价是非常巨大的(大多数嵌入式应用都是定点处理器)。相对于整数数学运算,浮点数学运算慢的要死。每个操作都会调用某个库来实现相应的函数,而这个库通常相当大。即使所使用的浮点数学非常简单,应用程序的大小也是非常惊人的。

(标准的输入输出函数(例如printf和iostream)通常包含浮点处理。即使代码中没有使用浮点,但如果使用了这些函数,那么代码还是会包含浮点算术库。)

除非有很好的理由,否则就应该像躲避瘟疫一样避开浮点数。如果不能避开,可以用伪装。

 

先介绍二级制换算,这是后面的基础。

除法运算是个成本相对较高的步骤,但是如果是除以常数,则有些方法可以解决这个问题,我们可以将除法用位运算来近似。

以Input/6为例。

Input/6如果将分子和分母都放大同样大的倍数,然后将分母换成离它最近的能用2的幂表示的数,则分母可以写成2的多少次方,然后就可以换成移位运算了。

 

表1:用2的幂为除数近似1/6

乘数

除数

等价移位

结果

误差%

1

6

0.166 666 667

0

3

16

4

0.1875

12.5

5

32

5

0.156 25

6.2

11

64

6

0.171 875

#include <iostream> #include <cstdio> // #include <cmath> using namespace std; //错误答案 // int main(){ // double N; // cin >> N; // double moneys[12] = {100.00,50.00,20.00,10.00,5.00,2.00,1.00,0.50,0.25,0.10,0.05,0.01}; // bool flag1 = 1; // bool flag2 = 1; // printf("NOTAS:\n"); // for (int i = 0;i < 6;i ++){ // printf("%d nota(s) de R$ %.2lf\n",(int)(N/moneys[i]),moneys[i]); // // N %= moneys[i]; 坑1:浮点数不能用%,只可整数,无符号整数使用 // N = fmod(N,moneys[i]); // } // printf("MOEDAS:\n"); // for (int i = 6;i < 12;i ++){ // printf("%d moeda(s) de R$ %.2lf\n",(int)(N/moneys[i]),moneys[i]); // N = fmod(N,moneys[i]); // } // return 0; // } // 坑2:上面做法错误原因——浮点数表示不准确(因为某些十进制小数在计算机二进制表示为 // 循环小数,而二进制只能用有限位的数字表述,所以最终只能用极其近似的二进制表示),和 // 因为浮点数表示不准确进而导致的舍入误差(由于只能用极其近似的二进制表示,故浮点数进 // 行运算时,只能算出非常近似于预期值的结果) // 解决办法:把需要运算的浮点数同乘以n+0.5,强转整数再运算,避开舍入误差,最后再/n // 正确答案 int main() { double N; cin >> N; int amount = (int)(N * 100 +0.5); int moneys[12] = {10000,5000,2000,1000,500,200,100,50,25,10,5,1}; printf("NOTAS:\n"); for (int i = 0; i < 6; i++) { printf("%d nota(s) de R$ %.2lf\n", amount / moneys[i], moneys[i] / 100.0); amount %= moneys[i]; // 使用整数的取余 } printf("MOEDAS:\n"); for (int i = 6; i < 12; i++) { printf("%d moeda(s) de R$ %.2lf\n", amount / moneys[i], moneys[i] / 100.0); amount %= moneys[i]; } return 0; }翻译成python代码
03-26
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值