How can you format an double like 12345.0 to be printed as 1.234E+04?
I want to print something like this:
int N = 1024;
int time = 3476;
printf("%f", (N/time));
Where the output would be: 3.394531E+00
You could either use float for your variables or cast some of the variables to floating-point type like this:
printf("%f", ((float)N/time));
If you want to have your numbers always in Scientific notation http://www.cplusplus.com/reference/cstdio/printf/ you can replace the format with "%e".
It's worth noting that printf expects double by default for all f F e E g G a A.
As commented and answered by others #Some programmer dude: perform the division using floating-point math and not integer math.
Insure the correct a/b vs b/a is done to achieve "output would be: 3.394531E+00"
Use the "%.nE" format (where n is the precession) to print in exponential notation. "%E" alone will act like "%.6E".
"%e" is like "%E" except is uses an 'e' vs. 'E' in the output.
#include <stdio.h>
int main(void) {
int N = 1024;
int time = 3476;
printf("%.6E\n", 1.0*N/time);
printf("%.6E\n", 1.0*time/N);
printf("%.3E\n", 12345.0);
return 0;
}
Output
2.945915E-01
3.394531E+00
1.234E+04
First you need to avoid the integer division. Cast N to a double for instance (then the division will be with decimals).
And use the %e format (%E for a big-e), for 6 decimals:
printf("%.6E", (double)N/time);
Related
How can I get a float or real value from integer division? For example:
double result = 30/233;
yields zero. I'd like the value with decimal places.
How can I then format so only two decimal places display when used with a string?
You could just add a decimal to either the numerator or the denominator:
double result = 30.0 / 233;
double result = 30 / 233.0;
Typecasting either of the two numbers also works.
As for the second part of the question, if you use printf-style format strings, you can do something like this:
sprintf(str, "result = %.2f", result);
Bascially, the ".2" represents how many digits to output after the decimal point.
If you have an integer (not integer constant):
int i = 20;
int j = 220;
double d = i/(double)j;
This is the simplest way to do what you are trying to achieve, I think..
double result = 30/233.0f;
for iOS development (iPhone/iPad/etc) better to use float type.
float result = 30/233.0f;
I understand there are several topics same as mine, but I still don't really get it, so I'm expecting someone could explain this in a more simple but explicit way for me instead of pasting other topics' links, thanks.
Here's a sample code:
int a = 960;
int b = 16;
float c = a*0.001;
float d = a*0.001 + b;
double e = a*0.001 + b;
printf("%f\n%f\n%lf", c, d, e);
which outputs:
0.960000
16.959999
16.960000
My two questions are:
Why does adding an integer to a float ends up as the second output, but changing float to double solves the problem as the third output?
Why does the third output have the same number of digits with the first and second output after the decimal point since it should be a more precise value?
The reason why they produce the same number of decimal places, is because 6 is the default value. You can change that as in the edited example below, where the syntax is %.*f. The * can be either a number as shown below, or in the second case, supplied as another argument.
#include <stdio.h>
int main(void) {
int a = 960;
int b = 16;
float c = a*0.001;
float d = a*0.001 + b;
double e = a*0.001 + b;
printf("%.9f\n", c);
printf("%.*f\n", 9, d);
printf("%.16f\n", e);
}
Program output:
0.959999979
16.959999084
16.9600000000000009
The extra decimal places now shows that none of the results is exact. One reason is because 0.001 cannot be exactly coded as a floating point value. There are other reasons too, which have been extensively covered.
One easy way to understand why, is that a float has about 2^32 different values that can be encoded, however there is an infinity of real numbers within the range of float, and only about 2^32 of them can be represented exactly. In the case of the fraction 1/1000, in binary it is a recurring value (as is the fraction 1/3 in decimal).
I think the calculation a*0.001 will be done in double precision in both cases, then some precision is lost when you store it as a float.
You can choose how many decimal digits are printed by printf by writing e.g. "%.10lf" (to get 10 digits) instead of just "%lf".
I'm trying to convert the decimal portion of a double 247.32
into an int 32. I only need two decimal places.
I can cast the double as int and subtract from the double to get .32000
I can then multiply by 100 to get 32.000
But then when I try to cast that 32.000 as an int, it turns into 31.
Can I fix this?
Should I use a different datatype than a double to store that number?
Thanks
The problem (which skjaidev's answer doesn't solve) is that 247.32 cannot be represented exactly in binary floating-point. The actual stored value is likely to be:
247.31999999999999317878973670303821563720703125
So you can't just discard the integer part, multiply by 100, and convert to int, because the conversion truncates.
The round() function, declared in <math.h>, rounds a double value to the nearest integer -- though the result is still of type double.
double a = 247.32;
a -= trunc(a); /* a == 0.32 -- approximately */
a *= 100.0; /* a == 32.0 -- approximately */
a = round(a); /* a == 32.0 -- exactly */
printf ("%d\n", (int)a);
Or, putting the computation into a single line:
double a = 247.32;
printf("%d\n", (int)round(100.0 * (a - trunc(a))));
Actually, this is probably a cleaner way to do it:
double a = 247.32;
printf("%d\n", (int)round(100.0 * fmod(a, 1.0)));
Given input value x and output y:
char buf[5];
snprintf(buf, sizeof buf, "%.2f", fmod(x, 1.0));
y = strtol(buf+2, 0, 10);
Or just y = 10*(buf[2]-'0')+buf[3]-'0'; to avoid the strtol cost.
This is about the only way to do what you want without writing a ton of code yourself, since the printf family of functions are the only standard functions capable of performing decimal rounding.
If you have some additional constraints like that x is very close to a multiple of 1/100, you could perhaps cheat and just do something like:
int y = ((x+0.001)*100;
By the way, if your problem involves money, do not use floating point for money! Use integers in units of cents or whatever the natural smallest unit for your currency is.
Since you're only looking for 2 decimal places, this works for me:
double a = 247.32;
int b = (int) (a * 100)%100;
printf ("%d\n", b);
Update: See my comment below.
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;
}
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:
float myfloat;
if(sscanf(str, "%f", &myfloat) != 1)
/* String could not be converted */
else
/* String was converted, myfloat is usable */
#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:
char dummy;
if (sscanf(str, "%f%c", &float, &dummy) != 1) {
/* Parse error. */
} else {
/* Parsed cleanly. */
}
instead. However, sscanf with %f is likely to use strtod internally and cast to float anyway. The language in the C standard says:
a,e,f,g Matches an optionally signed floating-point number, infinity, or NaN, whose
format is the same as expected for the subject sequence of the strtod
function. The corresponding argument shall be a pointer to floating.
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.
I was going to say, simply use the code you already have, but assign the result of strod() to a float instead of a double. But your code is wrong in several ways.
Firstly, you cannot test errno unless an error has ocurred. Secondly, strtod() will not set errno except for things like range errors. If you pass it an invalid number, like "XYZ", it will not be set.
More correct use of strtod is:
char *p;
double d = strtod( "123.4xyz", & p );
if ( * p != 0 ) {
// not a number - in this case will point at 'x'
}
Using strtod() to read a float, you may lose some precision, but that's the price you pay for using floats - in general, unless you have a very good reason not to, you should always prefer the use of double to float.
strtof does not exist in C89, but it does in C99.
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 of 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;
}
Running the program:
$ ./a.out
Valid: 3.40282e+38
$ ./a.out 3.5e38
Invalid float: 3.5e+38
$ ./a.out -1e40
Invalid float: -1e+40
You may or may not need to add a test for correct strtod() return, depending upon whether there's a possibility of an overflow in double type as well.
On MSVC you can use _atoflt(), defined in stdlib.h