这是我想要做的事情:
float
一起使用,而不会丢失额外的零或不向用户的原始输入添加零。frac = num - (int)num
,然后乘以frac
,直到我们得到零作为余数。但是对于像 34.3400 这样的情况,这种情况就失败了 - 最后两个零点不会包含在这个方法中。通过
将浮点数转换为字符串char string[20];
sprintf(string, "%f", float_number);
sprintf
函数将浮点数作为字符串放置,但此处它也不会自动检测用户输入的精度,并在末尾用额外的零填充字符串(总精度为6)。因此,此处也未获得有关用户原始输入精度的信息。
那么,有没有办法完成这项工作?该号码必须取自用户的浮点号。有没有办法获得用户输入精度的信息?如果不可能,解释将非常有用。
答案 0 :(得分:1)
我想我明白你来自哪里。例如。在物理学中,无论你是写42.5
还是42.500
,都会隐含给出有效数字的数量。对于任何42.5
,x: 42.45 <= x < 42.55
代表任意数字42.500
和x: 42.4995 <= x < 42.5005
。
对于较大的数字,您可以使用科学记数法:1.0e6
表示带有x: 950000 <= x < 1050000
的数字x。
浮点数使用相同的格式,但使用二进制数字(有时称为位;))而不是十进制数字。但是有两个重要的区别:
要解决您的问题,您可以自己存储有效位数:
struct myNumber
{
double value;
int nsignificant;
};
当然,您必须自己解析输入,以找出nsignificant
中要放置的内容。此外,在这里使用至少 double
作为值,float
的精确度非常有限,无法让您走得更远。有了这个,你可以使用nsignificant
来确定一个正确的格式字符串,用于打印你想要的数字位数。
这仍然存在上述问题:您无法直接将十进制数字映射到位,因此绝不保证您的数字可以以您想要的精度存储。如果精确的十进制表示很重要,那么您将要使用不同的数据类型。 C# provides one,但C没有。你必须自己实施它。你可以从这样的事情开始:
struct myDecimal
{
long mantissa;
short exponent;
short nsignificant;
}
在这个结构中,您可以例如像这样放置1.0e6
:
struct myDecimal x = {
.mantissa = 1;
.exponent = 6;
.nsignificant = 2;
};
当然,这需要你编写很多自己的代码来解析和格式化这些数字。
答案 1 :(得分:0)
唯一的方法是创建一个具有原始字符串值和/或舍入所需精度的结构
答案 2 :(得分:0)
必须在用户输入期间作为 float 输入。
那么,有没有办法完成这项工作。
几乎。 “技巧”是注意用户输入的文本长度。下面将记住第一个非空白字符的偏移量和数字输入后的偏移量。
scanf(" %n%f%n", &n1, &input, &n2);
n2 - n1
为代码提供代表float
的用户输入的长度。如果用户输入采用指数表示法,十六进制FP表示法,无穷大,非数字,过多的前导零等,则此方法可能会被欺骗。但是对于直接十进制输入效果很好。
我们的想法是将数字打印到精度至少为n2 - n1
的缓冲区,然后确定要打印的小数部分的数量。
回想一下float
通常有大约6-7个显着的重要前导数字,因此尝试输入“123456789.0”之类的文字会产生float
exact 值123456792.0
,输出将基于该值。
#include <float.h>
#include <math.h>
int scan_print_float(void) {
float input;
int n1, n2;
int cnt = scanf(" %n%f%n", &n1, &input, &n2);
if (cnt == 1) {
int len = n2 - n1;
char buf[len * 2 + 1];
snprintf(buf, sizeof buf, "%.*f", len, input);
char dp = '.';
char *p = strchr(buf, dp);
if (p) {
int front_to_dp = p + 1 - buf;
int prec = len - front_to_dp;
if (prec >= 0) {
return printf("<%.*s>\n", prec, p+1);
}
}
}
puts(".");
return 0;
}
int main(void) {
while (scan_print_float()) {
fflush(stdout);
}
return EXIT_SUCCESS;
}
输入/输出
43.3423
<3423>
45.3400
<3400>
-45.3400
<3400>
0.00
<00>
1234.500000
<500000>
.
.
为了有力地处理这种情况和各种边缘情况,代码应该将用户输入读作 text 而不是float
。
注意:float
通常代表约2 32 数字完全。
43.3423
通常不是其中之一。相反,它的确具有43.3423004150390625
43.3400
通常不是其中之一。相反,它的确具有43.340000152587890625