自己写一个软件渲染器的时候,无意中发现float转换int非常耗时,于是查阅文章,这才有了这个命题,以前不清楚还有这么个机制。网上看了很多文章,搜索到了一个数字6755399441055744,这个是double快速转换int的一个magic number。至于原理我一知半解,主要看效果。经测试,这个函数的效率比c++直接float转int高很多,记录下来以便备忘。

//
// 将64位浮点数转换为32位整数
// 小数部分将四舍五入到偶数
//
//用于double的magic number是1.5*2^52=6755399441055744.0
//对于double来说,相应的magic number就是1.5*2^36
//处理float的速度比汇编低1/3
//编译器优化情况下,比手写汇编快 inline int32_t f_toint(double x)
{
x += 6755399441055744.0;
return *(int32_t*)&x;
} //四舍五入,处理的数据范围是-2^22 ~ 2^22-1, -4194304.0 ~ 4194303.0
inline int32_t f_toint32(float x)
{
//取得符号位,设置掩码
uint32_t n = ((*(uint32_t*)&x) & 0x80000000) ? 0xFFC00000 : 0;
x += 12582912.0f;
return ((*(uint32_t*)&x) & 0x3FFFFF) | n;
}

f_toint32的原型是csdn论坛一个网友说的回复:

inline long magic_f2l( float x )
{
    static long mask[] = { 0x0, 0xffc00000 };
    static float trunc[] = { -.5f, .5f };
    int s = ( *(unsigned long*)&x )>>31;
    x += trunc[s];
    x += 12582912.f;
    return (*(long*)&x) & 0x3fffff  | mask[s];
}
 
这个里面用到了12582912这个魔法数字,和double转换那个是一样的,都可以用这个函数得到:

double float_magic_number(int bits)
{
    return 1.5 * STD::pow(2.0, double(bits));
}

但magic_f2l()这个函数效率并没有double版本的那么好,原因估计是运算运算太多了,于是我精简了一下:

inline long magic_f2l( float x )
{
    static long mask[] = { 0x0, 0xffc00000 };
    static float trunc[] = { -.5f, .5f };
    int s = ( *(unsigned long*)&x )>>31;//这里得到float的符号位,如果是负数,最后结果就和0xFFC00000进行or运算。这里有个位移操作
    x += trunc[s];//这里有个加法和数组取值操作
    x += 12582912.f;
    return (*(long*)&x) & 0x3fffff  | mask[s];//数组取值
}
 
经简化,完成如下函数,这个效率和double版本不相上下,稍微慢一丢丢(几个时钟周期),仍然把c++默认转换摔在后面。

inline int32_t f_toint32(float x)
{
//取得符号位,设置掩码
uint32_t n = ((*(uint32_t*)&x) & 0x80000000) ? 0xFFC00000 : 0;//一个三元操作符,直接储存掩码
x += 12582912.0f;//魔法数字加法
return ((*(uint32_t*)&x) & 0x3FFFFF) | n;//直接or运算
}

float(double)快速转换int的方法的更多相关文章

  1. sql server数据库如何存储数组,int[]float[]double[]数组存储到数据库方法

    原文地址:https://www.zhaimaojun.top/Note/5475296 将数组存储到数据库的方法 (本人平时同csharp编写代码,所以本文中代码都是csharp代码,有些地方jav ...

  2. 二进制&八进制&十六进制之间的快速转换------ 心算&笔算方法总结

    二进制数                   0&1两种元素: 8进制数                   0-7 八种元素: 十六进制数            0-9,a,b,c,d,e, ...

  3. 关于c中 int, float, double转换中存在的精度损失问题

    先看一段代码实验: #include<limits> #include<iostream> using namespace std; int main() { unsigned ...

  4. JAVA float double数据类型保留2位小数点5种方法

    /** * Java 两个整数相除保留两位小数,将小数转化为百分数 * java中,当两个整数相除时,由于小数点以后的数字会被截断,运算结果将为整数,此时若希望得到运算结果为浮点数,必须将两整数其一或 ...

  5. C++中将string类型转换为int, float, double类型 主要通过以下几种方式:

      C++中将string类型转换为int, float, double类型 主要通过以下几种方式: # 方法一: 使用stringstream stringstream在int或float类型转换为 ...

  6. QT中QString 与 int float double 等类型的相互转换

    Qt中 int ,float ,double转换为QString 有两种方法 1.使用 QString::number(); 如: long a = 63; QString s = QString:: ...

  7. [C++] string与int, float, double相互转换

    参考:http://blog.csdn.net/candadition/article/details/7342380 将string类型转换为int, float, double类型 主要通过以下几 ...

  8. boolean和Boolean, char和Character , byte和Byte, short和Short, int和Integer , long和Long , float和Float, double和Double的区别 , String和StringBuffer的区别

    Java提供两种不同的类型:引用类型和原始类型(内置类型).Int是java的原始数据类型,Integer是java为int提供的封装类. Java为每个原始数据类型提供了封装类. 其中原始数据类型封 ...

  9. 有关C++的数据类型(int,long,short,float,double等等)

    再看C++ prime plus 第六版的时候 对数据类型又一次有些乱了,在看了这篇博客后,重新清晰起来了. 有关C++的数据类型(int,long,short,float,double等等)

随机推荐

  1. 矩阵奇异值分解(SVD)

    转自:https://www.cnblogs.com/LeftNotEasy/archive/2011/01/19/svd-and-applications.html  (感谢,讲解的太好了) 在机器 ...

  2. 深入浅出Redis(二)高级特性:事务

    第一篇中介绍了Redis是一个强大的键-值仓储,支持五种灵活的数据结构.其实,Redis还支持其他的一些高级特性:事务.公布与订阅.管道.脚本等,本篇我们来看一下事务. 前一篇中我们提到,在Redis ...

  3. 打造极致性能数据库中间件丨LVS+Keepalive+华为云DDM之理论篇

    背景说明 华为云分布式数据库中间件(Distributed Database Middleware,简称DDM),专注于解决数据库分布式扩展问题,突破了传统数据库的容量和性能瓶颈,实现海量数据高并发访 ...

  4. boost的内存管理

    smart_ptr raii ( Resource Acquisition Is Initialization ) 智能指针系列的都统称为smart_ptr.包含c++98标准的auto_ptr 智能 ...

  5. Android 封装实现各种样式对话框

    先上图 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/disso ...

  6. [IT练习册]Python练习项目 思路

    1.爬虫:爬取如下网站一年的内容. http://www.calvarymoravian.org/dailytext 2.蛇形棋: 开发一个类似蛇形棋的游戏.最好基于Web. 3.爬虫+通讯录: 从公 ...

  7. NHibernate不支持复杂的linq,就一定要用DataTable这么低级吗

    有些linq,好不容易写出来,正想扬眉吐屁一番,不料用NHibernate一执行,却报错,说是不支持,我靠. 只好捏着鼻子写一大段sql,交给它.这种直接执行SQL的情况,我看我同事写的,全部都是返回 ...

  8. CentOS 7下Keepalived + HAProxy 搭建配置详解

    第一步:准备 1. 简介 本文搭建的是利用 Keepalived 实现 HAProxy 的热备方案,即两台主机上的 HAProxy 实例同时运行,其中全总较高的实例为 MASTER,MASTER出现异 ...

  9. 2强类型DataSet (2011-12-30 23:16:59)转载▼ 标签: 杂谈 分类: Asp.Net练习笔记 http://blog.sina.com.cn/s/blog_9d90c4140101214w.html

    强类型DataSet (2011-12-30 23:16:59) 转载▼ 标签: 杂谈 分类: Asp.Net练习笔记 using System; using System.Collections.G ...

  10. 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较(转)

    几大最短路径算法比较 几个最短路径算法的比较:Floyd        求多源.无负权边(此处错误?应该可以有负权边)的最短路.用矩阵记录图.时效性较差,时间复杂度O(V^3).       Floy ...