atof("0") returns 2 in float variable - c

I write c embedded on STM32F437VI. At some point, I need to parse some strings that contain numbers, as float numbers. I use atof and it works always with the correct result, except for this one weird case. If the string is 0 or 0.0 it gives 2.
I have included stdlib.h and even tried (float)atof() to typecast, but for some weird reason, the float variable has always the value 2 from the atof("0") operation and the double value has the correct 0.
Why is this happening? Thank you all in advance.
#include "stdio.h"
#include "stdlib.h"
int main(void)
{
char test[] = "0";
float val1;
double val2;
val1 = atof(test);
val2 = atof(test);
return 0;
}
I expect the obvious result of 0 to the float variable as well, but it keeps getting the fixed 2 value.
UPDATE:
This code section is part of a much bigger project and there is no point in elaborating on the project. I have custom Makefile with LDFLAG option
"-mfloat-abi=hard -mfpu=fpv4-sp-d16 -u _printf_float".
Could this affect this issue?
As the MCV example is concerned, in main.c I have the above code section and I got the results mentioned.
Can anybody think of any reason atof() behaves in this way?
Of course I have used online c compiler as well with the exact same code and the result is of course 0. I guess if something was very very wrong with the stdlib library, then atof() would not work for all the other cases as well. But it fails only for "0" and only with the result 2 assigned to the float variable.
I watch the variables realtime with Ozone debugger software.
Could the reason be the floating point implementation on STM32F4 mcu used? A missing parameter in the custom Makefile or something like that?

First, your question lacks a Minimal, Complete, and Verifiable example.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char test[] = "0";
float val1;
double val2;
val1 = atof(test);
printf("%f\n", val1);
val2 = atof(test);
printf("%f\n", val2);
}
Output:
0.000000
0.000000
<°)))<()
Or your standard library implementation is fubar.

It looks like the cause of your problem is in the updated question text:
UPDATE: This code section is part of a much bigger project and there is no point in elaborating on the project. I have custom Makefile with LDFLAG option
"-mfloat-abi=hard -mfpu=fpv4-sp-d16 -u _printf_float".
Assuming these options are changes vs the defaults, what you're doing is telling the compiler to generate code for a different ABI from your toolchain's library ecosystem. The code generated for main expects the result of atof in a floating point register, but atof is using the standard ABI, which passes floating point arguments and return values in general-purpose registers. Thus, main is just reading whatever junk happens to be left in the floating point registers used for return values.
See if your problem goes away if you remove -mfloat-abi=hard. If so, you've probably found your problem. You need to either build a toolchain and libraries for the hardfloat ABI, or stick with the default non-hardfloat calling convention.

Related

Why does this float array element print properly, but not this double array element?

I'm learning the basics of C right now.
I am trying to input data into an array. After some trial and error, I've found that I can do what I need to using a float array as opposed to a double array.
#include <stdio.h>
int main()
{
float x[4]={2.2,3.3,4.4,5.5};
scanf("%f",&x[3]);
printf("%f",x[3]);
return 0;
}
The user input 3 would result in 3.000000
However in this version:
#include <stdio.h>
int main()
{
double x[4]={2.2,3.3,4.4,5.5};
scanf("%f",&x[3]);
printf("%f",x[3]);
return 0;
}
The user input 3 would result in 5.500001
Why is this, and how can I properly enter values to/print out the array values?
First, you have memory trampling due to use of incorrect format specifiers. First, the corrected example, with less "noise".
#include <stdio.h>
int main(void)
{
double x = 5.5;
scanf("%lf", &x);
printf("%lf", x);
return 0;
}
Second, you should try and avoid scanf() in general for string parsing, and considering reading on a per-line basis (ie: fgets() or some other mechanism), and then writing a parser. There is a plethora of closed/dupe questions on this site for questions like yours alone. Plus, other things, like newlines being left in the input buffer.
Finally, three good points:
David C. Rankin notes: use gcc -Wall -Wextra to catch all compiler warnings. Append -Werror if you want to force yourself not to allow any warnings to get by).
Look into learning how to to use gdb to debug programs. It's dead simple: compile with debug symbols and debug mode (and zero optimizations) configured via: gcc -O0 -ggdb, and then gdb my_program_name; joy!).
Consider building your programs with stack smash detection enabled (gcc -fstack-protector-strong). It will intentionally "crash" (assert) your programs early if you're doing something very wrong, like what happened in your example. It lets you discover serious memory trampling issues during testing rather than in production. Now isn't a bad time to learn about valgrind, strace, ptrace, helgrind, perf, etc, while you're at it.
Best of luck!

rounding to desired digits in MATLAB and C

I've read the questions regarding the implementation of rounding in C, inspired by MATLAB round function and I followed their advice but the result is not at all what it should be. Here's part of my code regarding this issue:
movmean_h[i]=(double)sum/(f-b);
mexPrintf("\t movmean_h[%d]=%e",i,movmean_h[i]);
movmean_h[i]=(double)round(movmean_h[i]*n)/n;
mexPrintf("\t movmean_h[%d]=%e",i,movmean_h[i]);
And part of the result is like this(this code is run in a loop):
movmean_h[10261]=2.283693e-13 movmean_h[10261]=1.668138e-06
movmean_h[10261]=2.283693e-13 movmean_h[10261]=1.668138e-06
movmean_h[10262]=2.288172e-13 movmean_h[10262]=1.483963e-06
movmean_h[10263]=2.292687e-13 movmean_h[10263]=-8.838173e-07
movmean_h[10264]=2.297219e-13 movmean_h[10264]=0.000000e+00
movmean_h[10265]=2.292835e-13 movmean_h[10265]=2.138378e-06
movmean_h[10266]=2.288319e-13 movmean_h[10266]=1.409754e-06
movmean_h[10267]=2.283839e-13 movmean_h[10267]=0.000000e+00
movmean_h[10268]=2.279412e-13 movmean_h[10268]=-2.147484e-06
movmean_h[10269]=2.275056e-13 movmean_h[10269]=-2.147484e-06
movmean_h[10270]=2.270787e-13 movmean_h[10270]=-2.147484e-06
movmean_h[10262]=2.288172e-13 movmean_h[10262]=1.483963e-06
movmean_h[10263]=2.292687e-13 movmean_h[10263]=-8.838173e-07
movmean_h[10264]=2.297219e-13 movmean_h[10264]=0.000000e+00
movmean_h[10265]=2.292835e-13 movmean_h[10265]=2.138378e-06
movmean_h[10266]=2.288319e-13 movmean_h[10266]=1.409754e-06
movmean_h[10267]=2.283839e-13 movmean_h[10267]=0.000000e+00
movmean_h[10268]=2.279412e-13 movmean_h[10268]=-2.147484e-06
movmean_h[10269]=2.275056e-13 movmean_h[10269]=-2.147484e-06
movmean_h[10270]=2.270787e-13 movmean_h[10270]=-2.147484e-06
The answers do not match at all, not in order and not in the decimals, which in theory they would match.
And 'n' is defined as:
long int n=pow(10,15);
So my question is why my code is wrong, or is there something I'm missing?
By the way I am writing my C code for a MATLAB mex-file.
Code lacked a declaration of declaration of double round(). Older compilers allow this, yet interpret the result then an int. Code output is then quite bizarre. The hint, for me, was that many nearby double inputs had the same result.
// add
#include <math.h>
10^15 doesn't fit into a long int on a Windows machine. Use a double.
double n = pow(10, 15);
movmean_h[i]=(double)sum/(f-b);
mexPrintf("\t movmean_h[%d]=%e",i,movmean_h[i]);
movmean_h[i]=round(movmean_h[i]*n)/n;
mexPrintf("\t movmean_h[%d]=%e",i,movmean_h[i]);

Output not match the code in c (double variable)

I am new with c and I'm trying to use doubles variable. Unfortunately, the compiler (Code::Blocks) seems to ignore absolutely what i'm writing.
#include<stdio.h>
int main()
{
double x=1.03;
printf("x: %lf",x);
return 0;
}
and the output is:
x: 0.000000
what is the problem?
Use %f instead of %lf. Doubles only need %f; see the "specifiers" table here.
If printf is looking for a larger value than you are providing, what prints out will be affected by what happens to be in memory near the x argument that you provided. In this case, I'm guessing that's 0.
Edit: Thanks to #Olaf for pointing out that the specification says %lf should work just fine. Apparently the OP's compiler or compiler version is nonstandard. Alternatively, perhaps the project settings are selecting nonstandard compiler behaviour. (I suppose the compiler or library implementation of printf could be buggy, as well.)

Printing control with C

when i execute the below code, the compiler returns the message "(.text+0x31): undefined reference to 'sqrt'". but if i take away the q* the compiler correctly gives me 8.000000
i'm trying to get the program to multiply the INCREMENT by 1 (and eventually 2 and 3 when i write the loop in).
how come the below doesn't work?
#include <stdio.h>
#include <math.h>
#define INCREMENT 64
int main ()
{
int q = 1;
printf("%f", sqrt(q*INCREMENT));
return 0;
}
You probably need to link to the math library. (though I thought visual C++ does this automatically...)
The reason why it works without the q is because the compiler is optimizing out the sqrt since it's a constant.
The code is correct c code. I tested it under vs 2010 and it returned the value 8. However it is not correct c++ code. sqrt becomes ambigueous when the argument is an integer. Is it possible that your source file has a .cpp extension, instead of a .c extension?

how to put an array character into the equation?

i try to put 8 byte character into the equation causing a lot of error,what i'm supposed to do to make sure the equation can take the static value and produce output in the 8 bytes.
#include <math.h>
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
void voltage_measure(void);
void main(void) {
voltage_measure();
}
void voltage_measure(void) {
char Van1[8],VA;
char Vbn[8],VB;
char Vcn[8],VC;
char AC[4],ac;
char BC[4],bc;
char AB[4],ab;
double Vab1,Vab2,Vbc1,Vbc2,Vac1,Vac2;
double Vab[8],Vbc[8],Vac[8];
Van1[0]=0xF0;
Van1[1]=0x00;
Van1[2]=0x00;
Van1[3]=0x00;
VA=0x000000F0;
Vbn[0]=0x78;
Vbn[1]=0x00;
Vbn[2]=0x00;
Vbn[3]=0x00;
VB=0x78;
Vcn[0]=0x3C;
Vcn[1]=0x00;
Vcn[2]=0x00;
Vcn[3]=0x00;
VC=0x3C;
AB[0]=0xB4;
AB[1]=0x00;
ab=0xB4;
AC[0]=0x2D;
AC[1]=0x00;
ac=0x2D;
BC[0]=0x5A;
BC[1]=0x00;
bc=0x5A;
Vab1=(VB*sin(ab))*(VB*sin(ab)) ;
Vab2=(VA+(VB*cos(ab)))*(VA+(VB*cos(ab)));
Vab[4]=sqrt(Vab1+Vab2);
Vbc1=(VC*sin(bc))*(VC*sin(bc));
Vbc2=(VB+(VC*cos(bc)))*(VB+(VC*cos(bc))) ;
Vbc[4]=sqrt(Vbc1+Vbc2);
Vac1=(VC*sin(ac))*(VC*sin(ac));
Vac2=(VA+(VC*cos(ac)))*(VA+(VC*cos(ac)));
Vac[4]=sqrt(Vac1+Vac2);
}
This is what I have understood as yet,
you want to do arithmetic with double precision that has several parameters
you would like to store the parameters in char variables (maybe to save on space?)
I don't know why you try to write VA=0x000000F0; when its a char (1 byte) variable
the static value you refer are probably the constants VA etc
It might be useful to have all these working in the arithmetic at double precision
when you use the sin and sqrt kind of functions, they will work at double anyways
you do not have a main function listed here;
it would be there in your actual file (that compiles this code)
so, i am also assuming you have things like math.h included
and the math library on the compile command
that is, you do get the binary compiled without errors
maybe you can elaborate the problem you are facing a little more?
Update from comment 1.
When you say, "character with 8 byte array" -- are you trying to create a double with an 8 char array?
Update from comment 2.
If your answer is in double, you can catch it in a double variable.
A double is already 8-bytes (on most platforms).
Is there a special reason to get it into a char array or a byte array?
Update from comment 3.
The link error implies you did include a math library for the linking.
The header just gives function prototypes for compilation.
With gcc, it would be -lm on the command line.
Update from comment 4.
To convert a double to an integer value check this page,
How can I convert a floating-point value to an integer in C?
Is the trouble that plain char on your machine is signed, so numbers such as 0xF0 are treated as -16 instead of +240? Did you know that on some machines, this is what will happen?
Concerning your link error you mentioned in the comments: including math.h is not enough, you have to tell the linker to add the library as well. Try adding "-lm" in your command line.

Resources