首先,我的上下文是需要将浮点文字(字符串)转换为float / double值的编译器编写器。在过去的15年里,我没有做任何浮点编程,所以我很确定这是一个完全愚蠢的新手问题。
double res;
errno=0;
*res = strtod((const char*)literal,NULL);
if (errno==ERANGE) throw_a_literal_out_of_range_exception();
return res;
但是c运行时库中没有“strtof”函数?
编辑:澄清。我已经知道字符串'literal'是C浮点的有效模式。它已经通过了正则表达式测试。我只想检查是否存在范围/精度问题。
原因在于用户可以编写的Eiffel源代码
a := {REAL_32} 3.1415
b := {REAL_32} 3.0E200
将写入的浮点数explit转换为32位浮点数。我认为在第二种情况下,编译器应检测到该值超出范围并引发错误或至少发出警告。
答案 0 :(得分:9)
在C89中你可以使用sscanf。
例如:
float myfloat;
if(sscanf(str, "%f", &myfloat) != 1)
/* String could not be converted */
else
/* String was converted, myfloat is usable */
答案 1 :(得分:6)
@Nicholas Goy:
我不认为sscanf(str, "%f, &float) == 1
(或!= 1
)确实做了所需的事情。
如果str
中有其他字符(例如“1.1foo”),它将无错误地解析,这可能是不合需要的。这可以通过以下方式纠正:
char dummy;
if (sscanf(str, "%f%c", &float, &dummy) != 1) {
/* Parse error. */
} else {
/* Parsed cleanly. */
}
代替。但是,带有sscanf
的{{1}}可能会在内部使用%f
并且无论如何都会转换为浮动。 C标准中的语言表示:
a,e,f,g匹配可选的带符号浮点数,无穷大或NaN,其中 格式与strtod的主题序列的预期相同 功能。相应的参数应该是浮动的指针。
哪种意味着这一点,对我来说似乎是对的(FreeBSD上的gcc 4.2.1)。使用上面的strtod
代码,“1.79e308”成功解析但值为+ inf,“5e-300”值为0.0,这些结果与您从{{1}获得的结果相同}和sscanf
。
反正。总而言之,我怀疑为什么OP想要使用float而不是double。
答案 2 :(得分:5)
我打算说,只需使用你已经拥有的代码,但是将strod()的结果赋给float而不是double。但是你的代码在几个方面都是错误的。
首先,除非出现错误,否则无法测试errno。其次,除了范围错误之外,strtod()不会设置errno。如果您传递一个无效的数字,例如“XYZ”,则不会设置它。
更正确地使用strtod是:
char *p;
double d = strtod( "123.4xyz", & p );
if ( * p != 0 ) {
// not a number - in this case will point at 'x'
}
使用strtod()来读取浮点数,你可能会失去一些精度,但这是你使用浮点数所付出的代价 - 一般来说,除非你有充分的理由不这样做,你应该总是喜欢使用double来浮。
答案 3 :(得分:4)
strtof
,但它在C99中存在。
答案 4 :(得分:4)
我建议先转换为双倍,然后转换为浮动。如果相对差异(f-d)/f
大于浮点精度(粗略地,1e-7
)那么数字可以比浮动中安全存储的数字多。
答案 5 :(得分:2)
在MSVC上,您可以使用stdlib.h中定义的_atoflt()
答案 6 :(得分:2)
由于您的价值在double
,因此您只需检查它是否超出float
的范围:
#include <stdlib.h>
#include <stdio.h>
#include <float.h>
int main(int argc, char *argv[])
{
double d = FLT_MAX;
if (argc > 1) {
d = strtod(argv[1], NULL);
}
if ((d > 0 && (d > FLT_MAX || d < FLT_MIN))
|| (d < 0 && (d < -FLT_MAX || d > -FLT_MIN)))
printf("Invalid float: %g\n", d);
else
printf("Valid: %g\n", d);
return EXIT_SUCCESS;
}
运行程序:
$ ./a.out
Valid: 3.40282e+38
$ ./a.out 3.5e38
Invalid float: 3.5e+38
$ ./a.out -1e40
Invalid float: -1e+40
您可能需要也可能不需要为正确的strtod()
返回添加测试,具体取决于double
类型是否有可能出现溢出。