博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
float 转定点计算加法和乘法
阅读量:6910 次
发布时间:2019-06-27

本文共 3047 字,大约阅读时间需要 10 分钟。

float 浮点数转成定点数计算其加法和乘法

需要注意的是,以下的程序是建立在下述条件为真的情况下的:

 
  1. (sizeof(float) == 4 && sizeof(long long) == 8 && sizeof(int) == 4) == ture

也就是说,一定要保证float和int是占4个字节(32bits),long long是占8个字节(64bits)的。

1, 浮点数转定点乘法
 
  1. void FixedPointMul(float&a, float& b, float& res)
  2. {
  3. int ia = *(int*)(&a);
  4. int ib = *(int*)(&b);
  5. //正负0的情况下,直接返回
  6. if (ia == 0x80000000 || ia == 0x0 || ib == 0x80000000 || ib == 0x0)
  7. {
  8. res = 0.0f;
  9. return;
  10. }
  11. //实际尾数还要加上最前面的1,这里用Long long的原因是两个24位数的乘法,最多是48位,已超出int
  12. long long ma = (ia & 0x7fffff) | 0x800000;
  13. long long mb = (ib & 0x7fffff) | 0x800000;
  14. //码位
  15. int ea = ((ia >> 23) & 0xff) - 0x7f;
  16. int eb = ((ib >> 23) & 0xff) - 0x7f;
  17. //mul
  18. long long mc = ma * mb;//相当于a<< (23-ea) a<<(23-eb)
  19. //计算阶码
  20. //先计算最高有效位
  21. int i = 0;
  22. long long tmp = mc;
  23. while (tmp != 0)
  24. {
  25. tmp >>= 1;
  26. i++;//得到MSB的位置
  27. }
  28. int ec = i - 1 - (23 - ea + 23 - eb) + 0x7f;
  29. //再右移mc MSB 到第24位
  30. //把MSB移位到第24位
  31. //把MSB移位到第24位
  32. if (i < 24)
  33. mc = (mc << (24 - i)) & 0xffffff;
  34. else
  35. mc = (mc >> (i - 24)) & 0xffffff;
  36. //
  37. //标记两个数的正负
  38. int sa = 0;
  39. if ((ia & 0x80000000) ^ (ib & 0x80000000))//xor
  40. sa = 1;//negative
  41. //float
  42. //拼接成float
  43. int rc = 0x00000000;
  44. rc = rc | (mc & 0x7fffff);
  45. rc = rc | ((ec << 23) & 0x7fffffff);
  46. //判断正负
  47. if (sa == 1)
  48. rc = rc | 0x80000000;
  49. res = *(float*)(&rc);
  50. return;
  51. }
2, 浮点转定点加法(减法可以认为是加上一个负数)
 
  1. #ifndef MAX
  2. #define MAX(X,Y) ((X)>(Y) ? (X) : (Y))
  3. #endif
  4. void FixedPointAdd(float& a, float& b, float& res)
  5. {
  6. int ia = *(int*)(&a);
  7. int ib = *(int*)(&b);
  8. //考虑正负0的情况
  9. if (ia == 0)
  10. {
  11. res = b;
  12. if(ib == 0x80000000)
  13. res = 0.0f;
  14. return;
  15. }
  16. if (ib == 0)
  17. {
  18. res = a;
  19. if (ia == 0x80000000)
  20. res = 0.0f;
  21. return;
  22. }
  23. //if ((ia & 0x7f800000 == 0x7f800000) | (ib & 0x7f800000 == 0x7f800000));
  24. //实际尾数还要加上最前面的1
  25. long long ma = (ia & 0x7fffff) | 0x800000;
  26. long long mb = (ib & 0x7fffff) | 0x800000;
  27. //码位
  28. int ea = ((ia >> 23) & 0xff) - 0x7f;
  29. int eb = ((ib >> 23) & 0xff) - 0x7f;
  30. //正负
  31. int sa = ia & 0x80000000;
  32. int sb = ib & 0x80000000;
  33. //移动到48位并加上符号运算
  34. if (ea > eb)
  35. {
    //让较大的数的MSB移动到第48位,较小的数对应的移动
  36. //这样的话,小数点对齐在哪里?
  37. ma <<= 24;
  38. //mb如何移动?//mb少移动:ea与eb的绝对值的差
  39. mb <<= (24 - std::abs(ea - eb));
  40. }
  41. else
  42. {
  43. mb <<= 24;
  44. ma <<= (24 - std::abs(ea - eb));
  45. }
  46. //考虑符号
  47. ma = (sa == 0 ? ma : -ma);
  48. mb = (sb == 0 ? mb : -mb);
  49. long long mc = ma + mb;
  50. int i = 0;
  51. long long tmp = 0;
  52. //结果符号
  53. tmp = 0x8000000000000000;
  54. int sc = ((mc & tmp) == 0 ? 0 : 1);
  55. if (sc == 1)//说明结果是负数
  56. {
  57. mc = -mc;
  58. }
  59. //计算阶码
  60. //先计算最高有效位
  61. tmp = mc;
  62. while (tmp != 0)
  63. {
  64. tmp >>= 1;
  65. i++;//得到MSB的位置
  66. }
  67. //code
  68. int ec = 0x7f;
  69. if (ea > eb)
  70. ec += ea + (i - 48);
  71. else
  72. ec += eb + (i - 48);
  73. //把MSB移位到第24位
  74. if (i < 24)
  75. mc = (mc << (24 - i)) & 0xffffff;
  76. else
  77. mc = (mc >> (i - 24)) & 0xffffff;
  78. //
  79. //float
  80. //拼接成float
  81. int rc = 0x00000000;
  82. rc = rc | (mc & 0x7fffff);
  83. rc = rc | ((ec << 23) & 0x7fffffff);
  84. //判断正负
  85. if (sc == 1)
  86. rc = rc | 0x80000000;
  87. res = *(float*)(&rc);
  88. return;
  89. }

最后需要注意的是,float占4个字节的情况下,在二进制情况下,共有24bit数字是精确数字,转换到十进制数, 只有6位有效数字是绝对精确的,所以在两个float数字比较其误差时,应注意,第7位及以后的数字是无意义的。

比如说:12345.67888和12345.6999其实对于float的内存来说是一样的,但是它们之间的绝对误差是:0.02111,达到了2%。
再比如:123456.000和123456.9999,在float的内存上是一样的,但是,其绝对差为0.9999。
所以用绝对差来表示两个float数是否相近,是不合理的。

转载于:https://www.cnblogs.com/beichen2012/p/5763747.html

你可能感兴趣的文章
对Html5 Web App 的背景调查研究
查看>>
SQL GROUP BY 语句
查看>>
.NET 动态脚本语言Script.NET 开发指南
查看>>
根绝ip限制访问
查看>>
ubuntu下virtualbox配置host-only网络
查看>>
Windows Server 2008 IIS7.0 发布html和Asp.net网站
查看>>
分布式搜索方案选型
查看>>
简单介绍一些HTML代码(字幕、音频和视频)
查看>>
[深入浅出Cocoa]iOS网络编程之NSStream
查看>>
Cocos2d-html5 笔记2: director
查看>>
程序猿你是否有这些理解误区?
查看>>
C语言整理——文件系统和文件访问
查看>>
阿里面试
查看>>
ECSHOP修改后台地址
查看>>
运动补偿与运动估计
查看>>
jQuery的一个关键函数
查看>>
表单模型+安装目录+侵入表单模型
查看>>
系统如何端子app弄root才干
查看>>
HTML表格边框的设置小技巧
查看>>
jmeter ---模拟http请求/发送gzip数据
查看>>