Unable to print right floating point value - c

I have my ZC706 board with dual arm cortex 32bit one. I am trying to run an algorithm over it, as a part of the code it has floating point values.
uint32_t int Ts = 69912;
float Ts_pico;
Ts_pico = 20*(10^-12)*Ts;
printf("Time stamp in picoseconds is %f", Ts_pico);
And it prints a value 4272595456.000000 instead of 1.39824*(10^-6)
So I tested by printing
printf("The float point value is %f", 1.39824);
It was fine printing out the following value.
Next, when i tested by printing
double f = 10^-6;
printf("The flloat point value is %f", f);
The value it has printed is -14401872.000000
How can I solve the issue with floating point values?

Didn't you want 10e-12 rather 10^-12?
10e-12 is a floating point double constant, although do note that 1e-12 is 10 raised to the -12th power. Your ^ is an abuse of the XOR operator.

Related

Why is this floating point addition result not correct?

I am trying to calculate the time in buffer in microseconds.
But I don't understand why the floating-point operation result of my code is not correct.
float time, sec;
int h, m;
sscanf(16:41:48.757996, "%d:%d:%f", &h, &m, &sec);
printf("buffer %s\n",buffer);
printf("hour %d\n",h);
printf("minute %d\n",m);
printf("seconde %f\n",sec);
time=3600*h+60*m;+sec;
printf("%f\n",time);
When I execute this code, I get the following result:
buffer 16:41:48.757996
heure 16
minute 41
seconde 48.757996
60108.757812
But I am expecting:
buffer 16:41:48.757996
heure 16
minute 41
seconde 48.757996
60108.757996
The result of the floating-point operation is not correct.
I think, you have a small typo in your code. Change
time=3600*h+60*m;+sec;
to
time=3600*h+60*m+sec; // remove ; from the apparent middle of the statement
^^
Otherwise, the sec value is becoming essentially useless.
That said, always check for the return value of sscanf() to ensure success.
EDIT:
As others have pointed out, the main reason behind losing the precision is due to the use of float type. It is nicely explained in this answer that, changing the variable type to double will increase the precision and you'll get a fine-grained result, as you've expected.
According to IEEE 754 encoding, many numbers will have small changes to allow them to be stored.Also, the number of significant digits can change slightly since it is a binary representation, not a decimal one.
Single precision (float) gives you 23 bits of significand, 8 bits of exponent, and 1 sign bit.
Double precision (double) gives you 52 bits of significand, 11 bits of exponent, and 1 sign bit.
Following code snippet will work for you
#include<stdio.h>
#include <stdlib.h>
int main()
{
double time, sec; // changed to double
double h, m;
sscanf("16:41:48.757996", "%lf:%lf:%lf", &h, &m, &sec);
printf("hour %lf\n",h);
printf("minute %lf\n",m);
printf("seconde %lf\n",sec);
time=3600*h+60*m+sec;
printf("%lf\n",time);
}
Change float to double if want more precision
double time, sec;
and use %lf in sscanf. You will get the desired result.
Live Demo
The calculation is good with doubles!
double time, sec;
sscanf(buffer, "%d:%d:%lf", &h, &m, &sec);
printf("buffer %s\n",buffer);
printf("heure %d\n",h);
printf("minute %d\n",m);
printf("seconde %f\n",sec);
P.TempsEmission=3600*h+60*m+sec;
printf("%lf\n",P.TempsEmission);

convert float pointing number to integer in c programing

I have a sine equation which return a float value like:
0.0034,.000006,6.1684332059801899768737349875082e-4.
I want to convert the corresponding float value to integer variables and pass it to a register to generate the particular sine wave graph.
Please help me out.
If you're getting values like 0.0034, you can't simply cast that to an int since it will come out as zero. In fact, the majority of floating point values between zero and one will come out as zero.
You need to first scale up the value, then cast it to an integer.
For example, to turn the output of a sine function into a value between -100 and 100, you could use something like:
int val = (int)(fpVal * 100);
That will turn the range (-1,1) (but mostly 0) into something more usable, (-100,100) (with slightly better distribution across the range).
You may also want to round the value rather than truncate it, to ensure the values generated more accurate represent the inputs.
You could try to save the float value into 3 unsigned integers, one for the values left of the decimal point and two for the values on the right of the decimal point.
For example, we get the float number "359.042042" and save it as variable flt.
int main(void)
{
unsigned int int1, int2, int0;
float flt = 359.042042;
int1 = floor(flt);
int2 = (flt - int1) * pow(10.0, 8.0);
int0 = 8 - log10(int2);
printf("%d.", int1);
while (int0 != 0)
{
printf("0");
int0--;
}
printf("%d", int2);
return 0;
}
int1 are the digits on the left side of the decimal points, int2 are the digits on the right and int0 are the "0" before int2.
This would print "359.042042". Good luck.

C: converting Farenheit to Celsius

int main (void)
{
int fahrenheit; // fahrenheit stands for fahrenheit
double c; // c stands for celsius
printf("Enter your fahrenheit, we'll covnvert it into celsius! ");
scanf("%f", &fahrenheit);
c = 5/9 * (fahrenheit - 32);
printf("Here is your %f in celsius!.\n");
return (0);
}
I've followed the code through break points and when it takes in my input the calculations are off, but the formula is correct. Some sort of logic error I can't put my finger on. Please help!
The scanf call uses the wrong format string. You are reading an int so you need it to be:
scanf("%d", &fahrenheit);
The expression 5/9 is evaluated using integer division. In fact the compiler can work it out at compile time. That expression evaluates to 0.
You need to perform floating point division. For instance:
5.0/9
Or:
5/9.0
Or
5.0/9.0
You just need at least one operand to be a floating point value.
Putting this into your expression, you can write:
c = 5.0/9.0 * (fahrenheit - 32);
and obtain the answer that you expect.
Your printf statement is wrong too. You should enable warnings and let the compiler tell you that. You meant to write:
printf("Here is your %f in celsius!.\n", c);
Integer math versus floating point math.
i = 5/9 // i is equal to 0
d = 5.0/9.0 // d is equal to whatever 5 divided by 9 would actually be
You also need to actually print the value:
printf("Here is your %f in celsius!.\n", c);
Short answer: Operations on integers return integers even if the variable you store the result on is a double. Divisions between integers are truncated.
You should write this instead:
c = 5.0/9.0 * (fahrenheit - 32.0);
Adding a ".0" (or even just a ".") to your constant makes them floating point values.

sprintf seems to be rounding up?

Something odd is occuring in my C code below.
I want to compare numbers and I round to 4 decimal places.
I have debugged and can see the data being passed in.
The value of tmp_ptr->current_longitude is 6722.31500000, and the value of tmp_ptr->current_latitude is 930.0876500000.
After using the sprintf statements:
charTmpPtrXPos = "6722.3150" and charTmpPtrYPos = "930.0876".
I expect the exact same results for speed_info->myXPos and speed_info->myYPos but strangely even though speed_info->myXPos = 6722.31500000 and the value of speed_info->myYPos > = 30.0876500000, the sprintf statements
charSpeedPtrYPos= "930.0877"
So basically the sprintf statement behaves differently for the second value and appears to round it up. Having debugged this I know the input to the sprintf statement is exactly the same.
Can anyone think of a reason for this?
sizeOfSpeedList = op_prg_list_size (global_speed_trajectory);
tmp_ptr= (WsqT_Location_Message*)op_prg_mem_alloc(sizeof(WsqT_Location_Message));
tmp_ptr = mbls_convert_lat_long_to_xy (own_node_objid);
sprintf(charTmpPtrXPos, "%0.4lf", tmp_ptr->current_longitude);
sprintf(charTmpPtrYPos, "%0.4lf", tmp_ptr->current_latitude);
speed_info = (SpeedInformation *) op_prg_mem_alloc (sizeof (SpeedInformation));
for (count=0; count<sizeOfSpeedList; count++)
{
speed_info = (SpeedInformation*) op_prg_list_access (global_speed_trajectory, count);
sprintf(charSpeedPtrXPos, "%0.4lf", speed_info->myXPos);
sprintf(charSpeedPtrYPos, "%0.4lf", speed_info->myYPos);
//if((tmp_ptr->current_longitude == speed_info->myXPos) && (tmp_ptr->current_latitude == speed_info->myYPos))
if ((strcmp(charTmpPtrXPos, charSpeedPtrXPos) == 0) && (strcmp(charTmpPtrYPos, charSpeedPtrYPos) == 0))
{
my_speed = speed_info->speed;
break;
}
}
printf() typically rounds to the nearest decimal representation, with ties sent to the “even” one (that is, the representation whose last digit is 0, 2, 4, 6, or 8).
However, you must understand that most numbers that are finitely representable in decimal are not finitely representable in binary floating-point. The real number 930.08765, for instance, is not representable as binary floating-point. What you really have as a double value (and what is converted to decimal) is another number, likely slightly above 930.08765, in all likelihood 930.0876500000000532963895238935947418212890625. It is normal for this number to be rounded to the decimal representation 930.0877 since it is closer to this representation than to 930.0876.
Note that if you are using Visual Studio, your *printf() functions may be limited to showing 17 significant digits, preventing you from observing the exact value of the double nearest 930.08765.
It is the difference between a float and a double.
OP is likely using tmp_ptr->current_latitude as a float and speed_info->myYPos as a double. Suggest OP use double though-out unless space/speed oblige the use of float.
int main() {
float f1 = 930.08765;
double d1 = 930.08765;
printf("float %0.4f\ndouble %0.4f\n", f1, d1);
return 0;
}
float 930.0876
double 930.0877
As the typical float uses a IEEE 4-byte binary floating point representation, f1 takes on the exact value of
930.087646484375
930.0876 (This is the 4 digit printed result)
This is the closest float value to 930.08765.
Like-wise, for a double, d1 takes on the exact value of
930.0876500000000532963895238935947418212890625
930.0877 (This is the 4 digit printed result)
In general, one could use more decimal places to reduce the likely-hood of this happening with other numbers, but not eliminate it.
Candidate quick fix
sprintf(charSpeedPtrYPos, "%0.4lf", (float) speed_info->myYPos);
This would first convert the value from speed_info->myYPos to a float. As non-prototyped parameters of type float are converted to double before being passed to sprintf(), the value would get converted back to double. The net result is a loss of precision in the number, but the same string conversion results.
printf("(float) double %0.4f\n", (float) d1);
// (float) double 930.0876
BTW: The l in "%0.4lf" serves no code generation purpose. It is allowed though.
See: http://www.cplusplus.com/reference/cstdio/printf/
A dot followed by a number specifies the precision, which is 4 in your case. Try to use a higher presicion if you need it. I have tried your number with a precision of 5 and it isn't rounded up anymore. So it should be..
sprintf(charSpeedPtrYPos, "%0.5lf", speed_info->myYPos);
..or any higher number which fits your needs.

Number of decimal digits in C

I like to change the number of decimal digits showed whenever I use a float number in C. Does it have something to do with the FLT_DIG value defined in float.h? If so, how could I change that from 6 to 10?
I'm getting a number like 0.000000 while the actual value is 0.0000003455.
There are two separate issues here: The precision of the floating point number stored, which is determined by using float vs double and then there's the precision of the number being printed as such:
float foo = 0.0123456789;
printf("%.4f\n", foo); // This will print 0.0123 (4 digits).
double bar = 0.012345678912345;
printf("%.10lf\n", bar); // This will print 0.0123456789
I experimented this problem and I found out that you cannot have great precision with float they are really bad .But if you use double it would give you the right answer. just mention %.10lf for precision upto 10 decimal points
You're running out of precision. Floats don't have great precision, if you want more decimal places, use the double data type.
Also, it seems that you're using printf() & co. to display the numbers - if you ever decide to use doubles instead of floats, don't forget to change the format specifiers from %f to %lf - that's for a double.
#kosmoplan - thank you for a good question!
#epsalon - thank you for a good response. My first thought, too, was "float" vs. "double". I was mistaken. You hit it on the head by realizing it was actually a "printf/format" issue. Good job!
Finally, to put to rest some lingering peripheral controversy:
/*
SAMPLE OUTPUT:
a=0.000000, x=0.012346, y=0.012346
a=0.0000003455, x=0.0123456791, y=0.0123456789
*/
#include <stdio.h>
int
main (int argc, char *argv[])
{
float x = 0.0123456789, a = 0.0000003455;
double y = 0.0123456789;
printf ("a=%f, x=%f, y=%lf\n", a, x, y);
printf ("a=%.10f, x=%.10f, y=%.10lf\n", a, x, y);
return 0;
}

Resources