C语言实现输出单精度、双精度小数十进制形式
2013-12-07 23:38
337 查看
在C语言里,用printf即可格式化输出小数,但是在某些特殊的场合,这些库函数却是不能使用的。故特意查找了一下单精度、双精度小数的二进制编码,自己实现一个输出十进制字符串的函数。具体代码如下所示。
测试函数如下:
结果如下:
#include"decimalString.h" #include<stdio.h> //若judge为0则返回ret值 #define RETURN_IF_ZERO(judge,ret) do{if(!(judge))return (ret);}while(0) #define MARK(len) ((1<<(len))-1)//二进制长度len的掩码 #define LOW_BINARY(d,low) ((d)&MARK(low))//取双字d的低low位 #define HIGH_BINARY(d,high) (((d)>>(32-(high)))&MARK(high))//取双字d的高high位 int lengthOfInt(int a);//a十进制绝对值的位数 //整数a十进制写入到字符串buf中 char*intToStr(int a,char*buf,int*length); //将小数点后若干高位写入字符串,高位为0需补上 //0<=decimal<1,且写入位数writeLen<=7 char*decimalToStr(double decimal,int writeLen,char*buf); int floatToInt(float f){//单精度的整数部分 return doubleToInt(f); } //双精度小数取整 //适用范围:数值在int整型范围以内 int doubleToInt(double db){ const int eOffset=1023;//指数偏移 const int wWidth=52,eWidth=11;//尾数位数,指数位数 int *binary=(int*)&db; int sign,e,w,r;//e:指数,w:尾数 sign=binary[1]>=0?1:-1;//正负号 e=LOW_BINARY(HIGH_BINARY(binary[1],1+eWidth),eWidth); e-=eOffset; RETURN_IF_ZERO(e>=0,0); RETURN_IF_ZERO(e!=0,sign); RETURN_IF_ZERO(e<=30,0x7ffffff*sign); w=LOW_BINARY(binary[1],wWidth-32); w<<=(64-wWidth); w|=HIGH_BINARY(binary[0],64-wWidth); r=(1<<e)|HIGH_BINARY(w,e); return sign*r; } //双精度小数f转换成小数位数precision位(最多13位小数)的十进制字符串 //小数范围需要在int范围以内 char*doubleToStr(double f,int precision,char*buf){ const int limit=7,dLimitTime=10000000;//小数位数一次写入位数最大限制 int len,zPart,dHign,sign; char*tmp=buf; double js=0.5;//四舍五入近似 sign=f<0?-1:1;//正负号 if(sign==-1) *tmp++='-'; f*=sign;//取绝对值 precision=precision<0?0:precision; precision=precision>13?13:precision; len=precision; while(len-->0) js/=10; f+=js;//四舍五入 zPart=doubleToInt(f);//整数部分 intToStr(zPart,tmp,&len);//写入整数部分 if(precision>0){//小数位数要求>0 dHign=precision<=limit?precision:limit; tmp[len]='.'; tmp+=len+1; f=f-zPart;//小数部分 decimalToStr(f,dHign,tmp);//小数高位部分先写入字符串 if(precision>limit){//limit位之后的小数的需要另外写入 f=f*dLimitTime;//放大倍数 f-=doubleToInt(f);// decimalToStr(f,precision-limit,tmp+limit); } } return buf; } //单精度小数f转换成小数位数precision位(最多7位小数)的十进制字符串 //小数范围需要在int范围以内 char*floatToStr(float f,int precision,char*buf){ precision=precision>7?7:precision; return doubleToStr(f,precision,buf); } //整数a十进制写入到字符串buf中 char*intToStr(int a,char*buf,int*length){ int pos=0; char*tmp; if(a<0){ a*=-1; buf[pos++]='-'; } tmp=buf+pos+lengthOfInt(a); if(length!=NULL)*length=tmp-buf; *tmp='\0'; while(a>9){ *--tmp=0x30|(a%10); a/=10; } *--tmp=0x30|a;//0x30='0' return buf; } //将小数点后若干高位写入字符串,高位为0需补上 //0<=decimal<1,且写入位数writeLen<=7 char*decimalToStr(double decimal,int writeLen,char*buf){ int t,tmp=writeLen; t=1; while(tmp-->0) t*=10; tmp=doubleToInt(decimal*t);//乘上10^writeLen再取整 buf[writeLen]='\0'; for(t=--writeLen;t>=0;t--){ buf[t]=(tmp%10)|0x30; tmp/=10; } return buf; } int lengthOfInt(int a){//a十进制绝对值的位数 int len=1; a=a>0?a:-a; while(a>9){ len++; a/=10; } return len; }
测试函数如下:
void testFDouble(){ double d2=12; float f2=-100,f3=12.8,f4=0.09; char tmp[65]; for(int k=0;k<40;k++){ double f=f2+k*10.0704008979423463423; //printf("%f-强制转换整数:%d\n",f,doubleToInt(f)); printf("%+.12f,函数输出:%s\n",f,doubleToStr(f,12,tmp)); } //printf("%f-强制转换整数:%d\n",-0.1,doubleToInt(-0.1)); //printf("%f-强制转换整数:%d\n",0.1,doubleToInt(0.1)); //printf("%f-强制转换整型:%d;函数转换:%d\n",f3,(int)f3,floatToInt(f3)); //printf("%f-强制转换整型:%d;函数转换:%d\n",f4,(int)f4,floatToInt(f4)); //printf("%s\n",intToBinary(12,tmp)); //printf("%s\n",intToBinary(*(int*)&f2,tmp)); //printf("%s\n",doubleToBinary(d2,tmp)); }
结果如下:
相关文章推荐
- 用汇编语言实现:以十进制形式输出双精度整型数
- C语言通过栈实现将十进制转为八进制输出
- 指针实现字符串IP地址转化为十进制IP地址输出-c语言
- C语言中十进制以二进制形式输出
- C语言整数十进制按照二进制形式输出程序
- C语言中的小数如果用int形式输出
- 把一个十进制整数以二进制数形式输出,for循环实现
- 从键盘输入某个十进制小数或整数,转换成对应的二进制小数并输出。 (查询十进制小数转换成二进制小数的算法,使用循环来实现。 最多保留小数位后7位数字即可)算法
- C语言实现十进制小数转二进制
- C++中如何用cout实现输出的填充,宽度,对齐及其精度控制
- C语言实现单链表逆序与逆序输出实例
- C语言小程序——十进制小数转二进制小数
- C语言:用递归函数DigitSum(n)实现输入1729,输出sum=1+7+2+9=19的值
- C语言实现多种类型变量的混合输出
- c语言之辗转相除法实现十进制转换为八进制
- C语言 输入字符串,按照宏定义形式输出相应字符串
- C语言实现因式分解输出
- 【c语言输入输出格式】 输出小数尾部没有0
- C语言递归算法系列_循环实现逆序和正序输出一个整数的每位数 (2)
- c语言实现二进制数转换为十进制