X86处理器包含两种类型的浮点数寄存器。第一种使用8个浮点寄存器组成浮点寄存器栈，另一种为向量寄存器(XMM,YMM)，它们对于单双精度的处理是不同的。本文将讨论两种模式下的浮点数计算速度问题。

```float a,b,c;
c=a*b;

fld         dword ptr [a]  //将a加载到浮点栈顶,即ST(0)=a;
fmul        dword ptr [b]  //将栈顶元素与b相乘，结果仍存于栈顶,即ST(0)=ST(0)*b
fstp        dword ptr [c]  //将栈顶元素弹出并保存于c,即c=ST(0),POP();```
```double  a,b,c;
c=a*b;

fld         qword ptr [a]
fmul        qword ptr [b]
fstp        qword ptr [c]  ```

Single precision division, square root and mathematical functions are calculated faster than double precision when the XMM registers are used, while the speed of addition, subtraction, multiplication, etc. is still the same regardless of precision on most processors (when vector operations are not used).

```float SqrtfloatV1(float *A,const int len)
{
float fSum=;
for (int i=;i<len;i++)
{
fSum+=sqrt(A[i]);
}
return fSum;
}

double SqrtdoubleV1(double *A,const int len)
{
double dSum=;
for(int i=;i<len;i++)
{
dSum+=sqrt(A[i]);
}
return dSum;
}```

```double  a,b;
int c;
c=a*b;

fld         qword ptr [a]
fmul        qword ptr [b]
call        @ILT+(__ftol2_sse) (0EC10CDh) //调用函数_ftol2_sse实现浮点数到整数的转换
mov         dword ptr [c],eax  ```

```double  a,b;
int c;
c=a*b;

movsd       xmm0,mmword ptr [a]
mulsd       xmm0,mmword ptr [b]
cvttsd2si   eax,xmm0  //cvttsd2si指令实现
mov         dword ptr [c],eax  ```

```float AddfloatV1(float *A,const int len)
{
int iSum=;
for (int i=;i<len;i++)
{
iSum+=A[i];//转成整数再求和
}
return (float)iSum;
}

float AddfloatV2(float *A,const int len)
{
float fSum=;
for (int i=;i<len;i++)
{
fSum+=A[i];
}
return fSum;
}```

(1)float与double混用(默认的浮点常量为double)

```float a,b;
a=b*1.2;

movd        xmm0,dword ptr [b]
cvtps2pd    xmm0,xmm0
mulsd       xmm0,mmword ptr [__real@3ff3333333333333 (13F646790h)]
cvtsd2ss    xmm0,xmm0
movss       dword ptr [a],xmm0  ```

（2）纯float

```float a,b;
a=b*1.2f;

movss       xmm0,dword ptr [b]
mulss       xmm0,dword ptr [__real@3f99999a (13F84678Ch)]
movss       dword ptr [a],xmm0  ```

```float MulfloatV1(float *A,const int len)
{
float fSum=;
for (int i=;i<len;i++)
{
fSum+=A[i]*1.2f;
}
return fSum;
}

float MulfloatV2(float *A,const int len)
{
float fSum=;
for (int i=;i<len;i++)
{
fSum+=A[i]*1.2;//默认的浮点常数是double
}
return fSum;
}```

```#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <math.h>
#include "Timing.h"
const int BUFSIZE =;
float buf[BUFSIZE];
double buf2[BUFSIZE];

//测试64位下float与double的速度差
float SqrtfloatV1(float *A,const int len);
double SqrtdoubleV1(double *A,const int len);

//测试浮点数转整数的速度
float AddfloatV1(float *A,const int len);
float AddfloatV2(float *A,const int len);

//测试64位下float与double混用速度
float MulfloatV2(float *A,const int len);
float MulfloatV1(float *A,const int len);

int main()
{
const int testloop=;
double interval;
srand( (unsigned)time( NULL ) );
for (int i = ; i < BUFSIZE; i++)
{

buf[i] = (float)(rand() & 0x3f);
buf2[i]= (double)(buf[i]);
}
//*****************************************************************//
//测试64位下float与double的速度差(32位无明显差异)
volatile float result1=;
startTiming();
for(unsigned int i=;i<testloop;i++)
{
result1=SqrtfloatV1(buf,BUFSIZE);
}
interval=stopTiming();
printf("SqrtfloatV1:\t%f,\t%lfms\n",result1,interval);

volatile double result2=;
startTiming();
for(unsigned int i=;i<testloop;i++)
{
result2=SqrtdoubleV1(buf2,BUFSIZE);
}
interval=stopTiming();
printf("SqrtdoubleV1:\t%lf,\t%lfms\n",result2,interval);
//*****************************************************************//

//*****************************************************************//
//测试浮点数转整数的速度(32为与64位均有明显差异)
volatile float result3=;
startTiming();
for(unsigned int i=;i<testloop;i++)
{
}
interval=stopTiming();

volatile float result4=;
startTiming();
for(unsigned int i=;i<testloop;i++)
{
}
interval=stopTiming();
//*****************************************************************//

//*****************************************************************//
//测试64位下float与double混用速度(32位无差异,因统一处理)
volatile float result5=;
startTiming();
for(unsigned int i=;i<testloop;i++)
{
result5=MulfloatV1(buf,BUFSIZE);
}
interval=stopTiming();
printf("MulfloatV1:\t%f,\t%lfms\n",result5,interval);

volatile float result6=;
startTiming();
for(unsigned int i=;i<testloop;i++)
{
result6=MulfloatV2(buf,BUFSIZE);
}
interval=stopTiming();
printf("MulfloatV2:\t%f,\t%lfms\n",result6,interval);
//*****************************************************************//
return ;
}

float SqrtfloatV1(float *A,const int len)
{
float fSum=;
for (int i=;i<len;i++)
{
fSum+=sqrt(A[i]);
}
return fSum;
}

double SqrtdoubleV1(double *A,const int len)
{
double dSum=;
for(int i=;i<len;i++)
{
dSum+=sqrt(A[i]);
}
return dSum;
}

float AddfloatV1(float *A,const int len)
{
int iSum=;
for (int i=;i<len;i++)
{
iSum+=A[i];//转成整数再求和
}
return (float)iSum;
}

float AddfloatV2(float *A,const int len)
{
float fSum=;
for (int i=;i<len;i++)
{
fSum+=A[i];
}
return fSum;
}

float MulfloatV1(float *A,const int len)
{
float fSum=;
for (int i=;i<len;i++)
{
fSum+=A[i]*1.2f;
}
return fSum;
}

float MulfloatV2(float *A,const int len)
{
float fSum=;
for (int i=;i<len;i++)
{
fSum+=A[i]*1.2;//默认的浮点常数是double
}
return fSum;
}```

## 汇编学习：float与double速度问题的更多相关文章

1. 从数据表字段 float 和 double 说起

今天在公司讨论项目重构的问题时,公司的 DBA 针对表中的字段大概介绍了一下 float 和 double 的存储方式.然后,我发现这个问题又回到了浮点数类型在内存中的存储方式,即 IEEE 对浮点数 ...

2. 第48条：如果需要精确的答案，请避免使用float和double

float和double主要为了科学计算和工程计算而设计,执行二进制浮点运算,这是为了在广泛的数值范围上提供较为精确的快速近似计算而精心设计的.然而,它们没有提供完全精确的结果,所以不适合用于需要精确 ...

3. 【转】JAVA程序中Float和Double精度丢失问题

原文网址:http://blog.sina.com.cn/s/blog_827d041701017ctm.html 问题提出:12.0f-11.9f=0.10000038,"减不尽" ...

4. Effective Java 第三版——60. 需要精确的结果时避免使用float和double类型

Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

5. Sql的decimal、float、double类型的区别

三者的区别介绍 float:浮点型,含字节数为4,32bit,数值范围为-3.4E38~3.4E38(7个有效位) double:双精度实型,含字节数为8,64bit数值范围-1.7E308~1.7E ...

6. float和double的精度

作者: jillzhang 联系方式:jillzhang@126.com 原网址:http://blog.csdn.net/wuna66320/article/details/1691734 1 范围 ...

7. float和double精度问题

System.out.println(new BigDecimal(253.90).doubleValue() * 100);25390.0精度正确 System.out.println(new Bi ...

8. float和double在内存中的存储方式

9. float、double的有效位数

Java中的浮点类型有两类,分别是float和double类型,其中float取_7__位有效数据,double取_15__位有效数据

## 随机推荐

1. C#常用操作类库三(XML操作类)

/// <summary> /// XmlHelper 的摘要说明. /// xml操作类 /// </summary> public class XmlHelper { pr ...

2. linux 安装sysstat使用iostat、mpstat、sar、sa(转载)

使用yum安装 #yum install sysstat sysstat的安装包是:sysstat-5.0.5-1.i386.rpm,装完了sysstat-5.0.5-1.i386.rpm后 就会有i ...

3. JS实现表单输入Enter键转换焦点框

<form> <input type="text" onkeypress="return handleEnter(this, event)"& ...

4. 通过 PowerShell 支持 Azure Traffic Manager 外部端点和权重轮询机制

Jonathan TulianiAzure网络 - DNS和 Traffic Manager高级项目经理﻿﻿ 在北美 TechEd 大会上,我们宣布了 Azure Traffic Manager将支持 ...

5. 用DIV+css写Table

做出的效果样式如下图, 1,首先考虑的是如何显示border,就像是分割代码,我把border分割为最外层DIV全border,和内层DIV的right和bottom的border,就是右边和下边. ...

7. 可能是最简单的把C++Lib包装成C#可用dll的方法

(想直接看结果的直接翻到最后) 之前对C++接触不多,最近工作需要,第三方给了一个C++的lib库,我们需要把它封装一下在C#中调用.对方要是直接给Dll就省事了... 研究了一下,基本有三个方向: ...

8. 【oracle】生成AWR报告

[第一步]找到awrrpt.sql文件 [ora11g@vm-kvm11820-app ~]\$ locate awrrpt.sql /DATA/opt/app/ora11g/product//rdbm ...

9. [转帖]/etc/security/limits.conf的含义

https://www.cnblogs.com/pzk7788/p/7250723.html /etc/security/limits.conf 是 Linux 资源使用配置文件,用来限制用户对系统资 ...

10. 如何缓解DDOS攻击

1.减少攻击面 (a) reduce the number of necessary Internet entry points,(b) eliminate non-critical Internet ...