在c中显示浮点数的格式化货币输出

时间:2013-12-21 10:12:34

标签: c

我编写了代码来显示浮点数的货币格式。以下是代码:

#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

看起来该程序舍入了它不应该的浮点值。我究竟在哪里弄错了?有什么帮助吗?

5 个答案:

答案 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位intdigits[20]太小了。)