我编写了代码来显示浮点数的货币格式。以下是代码:
#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);
}
以下是该程序的示例运行。
Please enter a number: 123546.36
123,546.35
看起来该程序舍入了它不应该的浮点值。我究竟在哪里弄错了?有什么帮助吗?
答案 0 :(得分:2)
float
仅适用于约7位有效数字。
为了获得更好的精确度,请使用double
。对大约15位重要人物来说这是好事。
答案 1 :(得分:2)
您需要确切的数字,还是更好的近似值?例如,这是一个银行的应用程序,他们在错误地放置一个便士时严重皱眉,或者它是否适用于游戏,其中一小部分金币并不重要?
正如其他人所写,浮点数仅精确到约7位有效十进制数字。这可能因编译器而异,因为C标准并未精确指定浮点数,但通常是正确的。如果你只需要更好的精度,你可以使用double或long double。
但是如果你需要确切的数字,你使用哪种浮点类型无关紧要:浮点数,双倍甚至超高速增强的双倍数。当您尝试存储它们时,某些数字会给出舍入错误。它类似于尝试使用有限数量的十进制数字存储1/3。你会遇到像0.10 + 0.10不等于0.20的问题。
如果您需要确切的数字,您可以将金额存储为整数的分数(或当地货币使用的数量):
int amount = 1405;
printf("Amount: %d.%02d\n", amount / 100, amount % 100);
答案 2 :(得分:1)
123546.36
:
The most accurate representation using float = 1.23546359375E5
The most accurate representation using double = 1.23546360000000000582076609135E5
使用float
:
1.23546359375E5
-1.23546000000E5
----------------
0.359375
最后:
(int)(0.359375 * 100) = 35
正如@Bathsheba所说,使用double
答案 3 :(得分:0)
C中的浮点数精度较低,只有7位有效数字。这是因为编译器完成了舍入。如果您想避免这种情况发生,请使用DOUBLE
(在这种情况下,我使用LONG DOUBLE
得到输出正确)而不是FLOAT
,因为它的精度高于FLOAT
。如果你想知道为什么这会发生在四舍五入的数字浮点数,请阅读以下链接中的文章阅读 -
What Every Programmer Must Know About Floating Point
这是修改后的源代码根据您的评论给出正确答案 -
#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);
}
答案 4 :(得分:0)
推荐新方法,让sprinf()
进行四舍五入。
sprintf()
将正确舍入到创建文本输出所需的小数位数。使用你认为合适的浮点数。它需要考虑许多边缘情况。然后只需要,
展示位置代码。
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);
}
除了OP陈述的问题,其他问题潜伏着:
1)负数while (n > 0)
2)float
大于int
的数字:n=(int)(num)
3)64位int
:digits[20]
太小了。)