30天自制操作系统吧 关注:1,380贴子:4,760
  • 0回复贴,共1

纸娃娃系统实现浮点数打印, sprintf(s, "%f", fv)的实现

只看楼主收藏回复

在纸娃娃系统中, 有用过 sprintf(s, "%f", fv) 这个方法的, 都知道只会输出 "######", 无法正常输出数值
在不改变底层stdlib包的情况下, 我们可以把%f 改成 %s, 即将浮点数先转化成字符串,再打印,
下面代码直接用吧^_^
int float2str(float v) {
int len = 7;
struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
char *c = (char *)memman_alloc_4k(memman, 32); //此处不可以char c[32]; 局部变量地址无法返回
char c0[32];
int i,j=0,v1=0,v1l=0,v2=0,v2l=0;
v1 = (int)v;
v -= v1;
if(v1 > 0) {sprintf(c0, "%d", v1); j = strlen(c0);} else { j = 0; }
if(j >= len) { //7位以上,超出精度直接放弃 2^31-1 = 2147483647
sprintf(c, "%d", v1);
return (int)c;
}
//计算整数部分位数
int v1t = v1;
while(v1t > 0) {
v1t /= 10;
v1l++;
}
v2l = len - (v1l > 1 ? v1l : 1); //得到小数部分可精确的位数, 整数长度最少为1, 0.xxx, 0也算一位
for(i = 0; i < v2l; i++) {
v *= 10;
v2 *= 10;
v2 += (int)v;
v -= (int)v;
}
if((int)(v*10) >= 5) { //四舍五入
v2 += 1; //五入
//四舍五入后验证是否有进位整数
int pre = 1;
for(i = 0; i < v2l; i++) { pre *= 10; }
if (v2 == pre) { //只有一种情况会进位,就是999 + 1 = 1000(例:保留3位小数时)
v1 += 1;
v2 = 0;
v2l = 0;
sprintf(c, "%d", v1);
return (int)c;
}
}
if(v2 == 0) { v2l = 0; }
//去除小数最后的0
while(v2 % 10 == 0) { //=0说明后面带0
v2l--;
v2 /= 10;
}
c0 = "%d.%0nd"; //小数位数最多为7位,所以此处只用一个n占位
c0[5] = v2l + 0x30; //将占位符换成数字
sprintf(c, c0, v1, v2);
return (int)c;
}
//调用
float fv = 1.00301f;
char *fvstr = (char*)float2str(fv);
sprintf(s, "%s", fvstr);
//输出结果: 1.00301


IP属地:福建1楼2023-03-16 10:22回复