目录
1 背景
把很小的数,它接近0但不等于0
通过计算过程中,会有精度丢失的可能!
解决的方法:把浮点数 字符串化,这样精度就不会丢失了
2 方法:文件、sprintf()、自写函数、ecvt()函数
文件读取 | sprintf() | 自写函数 | ecvt()函数 |
---|---|---|---|
效果最好 | 效果最好 | 效果好 | 效果稍差 |
速度快 | 几乎没有限制 速度快 | 限制多 | 限制少 |
2.1 文件读取
效果最好
见 https://blog.csdn.net/qq_40893824/article/details/105997362 1.3.1 小节
2.2 sprintf()函数
sprintf 跟 printf 用法上区别:
前者打印到字符串中
后者直接在命令行上输出
效果最好,速度还快,不知道复杂度是多少
解析:
int sprintf(char *string, char *format [,argument,...]);
int j = sprintf( buffer, " String: %s\n", s);
j = 返回写入的字符总数
buffer = string
" String: %s\n" = char *format
, s = [,argument,...]
基本使用代码:
#include<bits/stdc++.h>
#define num 100
using namespace std;
int main()
{
char buffer[num], s[] = "123456", c = 'd' ;
int i = 35, j, a = 1;
float f = 3.1415926f;
j = sprintf(buffer, "str[] = %s\n", s);
printf("第%d次:\n%s\n字符长度 j = %d\n\n\n", a++, buffer, j);
j += sprintf(buffer + j, "c = %c\n", c);
printf("第%d次:\n%s\n字符长度 j = %d\n\n\n", a++, buffer, j);
j += sprintf(buffer + j, "i = %d\n", i);
printf("第%d次:\n%s\n字符长度 j = %d\n\n\n", a++, buffer, j);
j += sprintf(buffer + j, "f = %f\n", f);
printf("第%d次:\n%s\n字符长度 j = %d\n\n\n", a++, buffer, j);
system("pause");
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/e73a5147f1d0e3fe4c7ebf981c070ac4.png)
读取 LDBL_MIN
#include<bits/stdc++.h>
#define num 180000
using namespace std;
int main()
{
char buffer[num];
int j;
long double f = LDBL_MIN;
j = sprintf(buffer, " LBDL_MIN = %-18000.17000Lf\n", f);
printf("%-18000.17000s", buffer);
system("pause");
return 0;
}
效果对比见 2.5
2.3 自写函数
思路:
注意正负号的处理!
- 把浮点数 (double)number 分为两部分 = 整数部分int_t 和 小数部分temp
int_t = (long long)number/1;
temp = number - int_t; - ini_t对10取余,将其存进字符数组首位,int_t = int_t/10; 继续循环刚刚的操作,直到int_t == 0 成立,就结束循环,将此时的字符数组前后元素一次交换
- 把 小数点’.'存进字符数组里,int_t = temp * 10; int_t对10取余存进字符数组,temp = temp*10 - int_t; 继续循环刚刚的操作,直到temp == 0 成立
- 把最后的 ‘\0’ 放进字符数组末尾
#include<bits/stdc++.h>
#define num 100000
using namespace std;
typedef struct
{
char data[num];
int length1, length2;
}Str;
void init(Str &str) // 初始化
{
memset(str.data, '\0', sizeof(str.data[0]));
str.length1 = str.length2 = 0;
}
void change(char str[], int low, int high) // low - high交换
{
while(low < high)
{
str[low] = str[low] + str[high];
str[high] = str[low] - str[high];
str[low] = str[low] - str[high];
low ++;
high--;
}
}
void print(Str str) // 输出 str 的信息
{
int i;
for(i = 0; i <= str.length2; i++)
cout << str.data[i];
cout << endl;
if(str.data[0] == '-')
{
cout << "整数部分长度 = " << str.length1 - 1 << endl;
cout << "小数部分长度 = " << str.length2 - str.length1 - 1 <<endl << endl;
}
else
{
cout << "整数部分长度 = " << str.length1 << endl;
cout << "小数部分长度 = " << str.length2 - str.length1 - 1 <<endl << endl;
}
}
int main()
{
long double number, temp;
long long int_t, low;
int m, n, i;
Str str;
FILE *fp;
init(str); //初始化
number = LDBL_MIN;
cout << "number = LDBL_MIN = " << number << endl << endl;
if(number == 0)
{
str.data[0] = '0';
str.data[1] = '\0';
str.length1 = 1;
str.length2 = 0;
}
else
{
i = 0;
if(number < 0) //带负号
{
str.data[0] = '-';
i = 1;
}
int_t = (long long)number; // int_t 整数部分
temp = number - int_t; // temp 小数部分
if(temp < 0)
temp = -temp;
cout << "int_t = "<< int_t<< endl;
cout << "temp = "<< temp<< endl;
if(int_t == 0)
{
str.data[i] = int_t + '0';
i++;
str.length1 = 1;
}
else
{
while(int_t != 0)
{
str.data[i] = int_t%10 + '0';
i++;
int_t /= 10;
cout << i <<" ";
}
str.length1 = i;
cout << "123"<< endl;
}
if(str.data[0] == '-')
low = 1;
else
low = 0;
change(str.data, low, i-1);
str.data[i] = '.';
cout << "123"<< endl;
while(temp != 0)
{
//cout << "123"<< endl;
i++;
int_t = temp*10 ;
str.data[i] = int_t%10 + '0';
temp = temp*10 - int_t%10;
}
cout << "123"<< endl;
str.length2 = i;
str.data[i] = '\0';
}
cout << "str = ";
print(str);
fp = fopen("./range.txt", "w+");
fputs(str.data, fp);
fclose(fp);
system("pause");
return 0;
}
2.4 ecvt()函数
char* ecvt(double value, int ndigit, int *decpt, int *sign);
把一个双精度浮点数转换成一个字符串。
- value:要转换的浮点数
存储最多ndigit个数字值作为字符串,并添加 ‘\0’,value中数字个数超过ndigit,低位数字被舍入。少于ndigit个数字,用0填充。 - decpt:小数点位置的整数值, 从字符串的开头位置计算
0或负数指出小数点在第一个数字的左边。 - sign:数的符号
如果该整数为0,这个符号数为正数,否则为负数。
#include<bits/stdc++.h>
#define num 18000
using namespace std;
void change(char str[], int low, int high)
{
while(low < high)
{
str[low] = str[low] + str[high];
str[high] = str[low] - str[high];
str[low] = str[low] - str[high];
low ++;
high--;
}
}
int main()
{
double number;
long double number2;
long long temp;
int dec, sign;
char *str;
cout << "DBL_MIN = " << DBL_MIN << endl;
str = ecvt(DBL_MIN, num, &dec, &sign);
cout << "str = " << str << endl ;
cout << "dec = " << dec << endl;
cout << "sign = " << sign << endl <<endl;
cout << "LDBL_MIN = " << LDBL_MIN << endl;
str = ecvt(LDBL_MIN, num, &dec, &sign);
cout << "str = " << str << endl ;
cout << "dec = " << dec << endl;
cout << "sign = " << sign << endl <<endl;
system("pause");
return 0;
}
2.5 效果运行比较
sprintf() - LDBL_MIN:
上:自写函数;下:ecvt()函数
和 sprintf() 比较的话…
可以看到,自己编写的函数得到的有效数字 要比 ecvt()函数要多一些,但远远不如 sprintf()!
ecvt() 读不了LDBL_MIN,但自己写的函数勉强可以