First my context is that of a compiler writer who needs to convert floating point literals (strings) into float/double values. I haven't done any floating point programming the last 15 years so i'm pretty sure this is a total stupid newbie question.
double res;
errno=0;
*res = strtod((const char*)literal,NULL);
if (errno==ERANGE) throw_a_literal_out_of_range_exception();
return res;
but there is no "strtof" function in the c runtime library?
EDIT: To clarify. I already know that the string 'literal' is a valid pattern for a C floating point. It already passed a regular expression test. I just want to check if there is a range/precision problem.
The reason is in Eiffel source code a user can write
a := {REAL_32} 3.1415
b := {REAL_32} 3.0E200
To cast a written floating point number explit to a 32bit floating point. I think in the second case the compiler should detect that the value is out of range and raise an error or at least a warning.
In C89 you may use sscanf.
For example:
strtof
does not exist in C89, but it does in C99.On MSVC you can use _atoflt(), defined in stdlib.h
I suggest converting to double first, then cast to float. If the relative difference,
(f-d)/f
, is greater than float precision (roughly,1e-7
) then there are more digits than what can be safely stored in float.Since you have your value in a
double
, you can just check if it's outside of the range offloat
:Running the program:
You may or may not need to add a test for correct
strtod()
return, depending upon whether there's a possibility of an overflow indouble
type as well.@Nicholas Goy: I don't think
sscanf(str, "%f, &float) == 1
(or!= 1
) really does what's desired.If there are additional characters in
str
(e.g. "1.1foo"), it will parse without error, which is probably undesirable. This can be rectified by doing:instead. However,
sscanf
with%f
is likely to usestrtod
internally and cast to float anyway. The language in the C standard says:which sort of implies this, and it seems to be true for me (gcc 4.2.1 on FreeBSD). Using the above
sscanf
code, "1.79e308" parses successfully but has the value +inf, as does "5e-300" with the value 0.0, and these are the same results you'd get from(float) 1.79e308
and(float) 5e-300
.Anyway. All that said, I question why the OP wants to use float instead of double anyway.