Reputation: 31
I have written code to show currency format of a float number. Following is the code:
#include<conio.h>
#include<stdio.h>
void showCurreny(float num);
int main()
{
float usernum;
printf("Please enter a number: ");
scanf("%f",&usernum);
showCurreny(usernum);
getch();
}
void showCurreny(float num)
{
int digit;
int digits[20];
int n=(int)(num);
int count=0;
float decpart=(num-n);
float n_decpart=decpart*100;
do {
digit = n % 10;
count++;
digits[count]=digit;
n /= 10;
} while (n > 0);
for(int i=count;i>0;i--)
{
if(i%3==0 && count-i>=1)
printf(",");
printf("%d",digits[i]);
}
printf(".%d",(int)n_decpart);
}
Below is a sample run of the program.
Please enter a number: 123546.36
123,546.35
It looks like the program rounds off the floating point value which it should not. Where exactly I am making a mistake? Any help?
Upvotes: 1
Views: 215
Reputation: 153457
Recommend new approach, let sprinf()
do the rounding.
sprintf()
will properly round to the number of decimal places desired creating the textual output. Use whatever floating point you see fit. There are many edge cases to consider which it handles. Then only ,
placement code is needed.
void AddCommas(char *buf) {
char *DP = strchr(buf, '.');
if (DP == NULL) {
return;
}
if (*buf == '-' || *buf == '+') {
buf++;
}
int Group = 3; // digit grouping left of the DP.
int Len = DP - buf;
int Commas = (Len - 1) / Group;
memmove(&DP[Commas], DP, strlen(DP)+1);
while (Commas > 0) {
memmove(&DP[Commas - Group], &DP[-Group], Group);
DP -= Group;
Commas--;
DP[Commas] = ',';
}
}
// Use float, double or long double. Adjust FLT_MAX_EXP & %.*f
void showCurreny(float num) {
char buf[FLT_MAX_EXP * 4 / 3 + 10]; // use right sized buffer
int DigitsAfterDP = 2;
sprintf(buf, "%.*f", DigitsAfterDP, num);
AddCommas(buf);
puts(buf);
}
Aside OP's stated problem, other problems lurk:
1) negative numbers while (n > 0)
2) float
numbers larger than int
: n=(int)(num)
3) 64-bit int
: digits[20]
too small).
Upvotes: 0
Reputation: 27632
Do you need exact numbers, or just better approximations? For example, is this an application for a bank, where they seriously frown upon misplacing a single penny, or is it for a game, where a few fractions of a gold piece doesn't matter that much?
As others have written, a float is only accurate to about 7 significant decimal digits. This can vary between compilers, since the C standard doesn't exactly specify what a float is, but it usually is true. If you just need better precision, you can use double, or long double.
But if you need exact numbers, it doesn't matter which floating point type you use: float, double or even ultra-turbo-wide doubledouble. Some numbers will give rounding errors when you try to store them. It is similar to when trying to store 1/3 with a finite number of decimal digits. You will get problems like 0.10 + 0.10 not being equal to 0.20.
If you need exact numbers, you can store the amount as a number of cents (or what the local currency uses) in an integer:
int amount = 1405;
printf("Amount: %d.%02d\n", amount / 100, amount % 100);
Upvotes: 2
Reputation: 41017
For 123546.36
:
The most accurate representation using float = 1.23546359375E5
The most accurate representation using double = 1.23546360000000000582076609135E5
Using float
:
1.23546359375E5
-1.23546000000E5
----------------
0.359375
Finally:
(int)(0.359375 * 100) = 35
As @Bathsheba say, use a double
Upvotes: 1
Reputation: 823
Floating Point Numbers In C Have Less Precision till only 7 significant figures. This happens due to the rounding done by the compiler. If you want to avoid this happening, use DOUBLE
(in this case I got the output correct using LONG DOUBLE
) rather than FLOAT
as it has more precision than FLOAT
. Incase you want to know why this happens with float in rounding numbers, Please give a read to the article at the following link -
What Every Programmer Must Know About Floating Point
Here Is the modified Source Code Which according to your comment Is giving correct answer -
#include<stdio.h>
void showCurreny(long double);
int main()
{
long double usernum;
printf("Please enter a number: ");
scanf("%Lg",&usernum);
showCurreny(usernum);
}
void showCurreny(long double num)
{
int digit,i;
int digits[20];
int n=(int)(num);
int count=0;
long double decpart=(num-n);
long double n_decpart=decpart*100;
do
{
digit = n % 10;
count++;
digits[count]=digit;
n /= 10;
}while (n > 0);
for(i=count;i>0;i--)
{
if(i%3==0 && count-i>=1)
printf(",");
printf("%d",digits[i]);
}
printf(".%d",(int)n_decpart);
}
Upvotes: 0
Reputation: 234695
A float
is only accurate to about 7 significant figures.
For better precision, use a double
. That's good to about 15 significant figures.
Upvotes: 2