Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 快速浮点到整数转换(截断)_C_Optimization_Floating Point_Truncate - Fatal编程技术网

C 快速浮点到整数转换(截断)

C 快速浮点到整数转换(截断),c,optimization,floating-point,truncate,C,Optimization,Floating Point,Truncate,我正在寻找一种方法,以快速且可移植的方式将浮点截断为int(IEEE 754)。原因是,在该功能中,50%的时间用于强制转换: float fm_sinf(float x) { const float a = 0.00735246819687011731341356165096815f; const float b = -0.16528911397014738207016302002888890f; const float c = 0.9996919862959675

我正在寻找一种方法,以快速且可移植的方式将
浮点
截断为
int
(IEEE 754)。原因是,在该功能中,50%的时间用于强制转换:

float fm_sinf(float x) {
    const float a =  0.00735246819687011731341356165096815f;
    const float b = -0.16528911397014738207016302002888890f;
    const float c =  0.99969198629596757779830113868360584f;

    float r, x2;
    int k;

    /* bring x in range */
    k = (int) (F_1_PI * x + copysignf(0.5f, x)); /* <-- 50% of time is spent in cast */

    x -= k * F_PI;

    /* if x is in an odd pi count we must flip */
    r = 1 - 2 * (k & 1); /* trick for r = (k % 2) == 0 ? 1 : -1; */

    x2 = x * x;

    return r * x*(c + x2*(b + a*x2));
}
float fm_sinf(float x){
常数浮点数a=0.007352468196870117313413561650968115F;
常数浮点b=-0.1652891139701473820701630200288890F;
常数浮点c=0.99969198629596757779830113868360584f;
浮动r,x2;
int k;
/*使x进入射程*/

k=(int)(F_1_PI*x+copysignf(0.5f,x))为了便于移植,您必须添加一些指令并学习两种汇编语言,但从理论上讲,您可以使用一些内联汇编将浮点寄存器的一部分移动到eax/rax ebx/rbx中,并手动转换您需要的内容。虽然浮点规范是一个难题,但我非常确定如果您使用汇编进行转换,您将更快,因为您的需求非常具体,而且系统方法可能更通用,对您的目的来说效率更低

您可以使用获取尾数和指数,并检查原始尾数,从而跳过到
int
的转换(使用
联合
)在适当的位位置(使用指数计算)确定(象限相关)
r

浮点->int强制转换的慢度主要发生在x86上使用x87 FPU指令时。要执行截断,FPU控制字中的舍入模式需要更改为舍入到零并返回,这往往非常慢

使用SSE而不是x87指令时,可以在不更改控制字的情况下进行截断。可以使用编译器选项(如GCC中的
-mfpmath=SSE-msse-msse2
)或将代码编译为64位

SSE3指令集具有
FISTTP
指令,可以在不更改控制字的情况下将其转换为整数。如果指令采用SSE3,编译器可以生成此指令


或者,C99
lrint()
函数将在当前舍入模式下转换为整数(除非更改,否则舍入为最近值)。如果删除
copysignf
项,您可以使用此功能。不幸的是,此功能在十多年后仍然不普遍。

我找到了Sree Kotay的一个,它提供了我所需的优化功能。

是什么让您认为汇编程序中的按位黑客攻击将比本机FP指令更快(我假设这里是x86)要将浮点转换为整数?@OliCharlesworth如果您愿意对输入设置一些约束,使用SSE Intrinsic确实有一个非常有效的技巧。强制转换之所以如此缓慢,是因为该语言要求输出对所有输入都是正确的。@Mysticial如果您中有人愿意分享这个技巧,那就太好了对于这一点和局限性-听起来很有趣。@Voo我想我以前看到过一个关于这一点的例子。但结果却是相反的。(
int
->
float
)第二个答案是要看的。虽然它是
int
->
float
,但它可以很容易地反转。我对
double
->
\uu int64
转换使用了类似的技巧。@神秘的感谢,真的很有趣。尽管我完全同意Paul R下面的评论,这个答案
很聪明,如果有点模糊的话
非常抱歉,在我匆忙的时候我忘了复制我的函数的一行。我还使用
int
的值来获得一个免费的
fmod
fmod
本身太慢了。@nightcracker:你试过
nearbyint()
对于这一部分?转换为整数并再次转换回浮点会很慢。@caf:事实上,后者非常快。只有转换为整数的速度非常慢。您是否尝试过使用
-ffast math
编译?还是省略了copysign函数并使用
lrint()
而不是(int)cast?您的常量是不必要的(或过于乐观)精确。单精度IEEE754仅适用于6位有效数字,双精度适用于15位数字,长双精度因编译器和体系结构而异,但即使在x86 FPU上,本机80位格式也仅适用于20位数字。如果您需要该精度级别,代码在任何情况下都无法工作,且精度任意库会慢得多。@Clifford:我知道它们太精确了,我总是喜欢计算35位,这样我就可以通过复制/粘贴来支持最高128位的任何内容。你验证了50%的时间是浮点数到int,或者50%的时间与那行代码有关?你想截断并保持浮点数格式吗?这不是如果指数告诉你小数点在尾数中,那么就把右边的所有数字都归零。如果小数点在左边(数字是一个分数,小于一),那么就编码为零。@dwelch:我证实了,50%到66%的时间都花在了演员身上。