6

MPFR ライブラリを使用して大きな数の計算を行いますが、小数点以下 8 桁の double も返します。

数値を char 配列に mpfr_sprintf するので、精度などは失われません。ドキュメントに桁区切りオプションが見つからなかった(または見逃した)ことを除いて、すべて問題ありません。

20043.95381376のような数値が与えられた場合、読みやすくするために20,043.95381376のように表現したいと思います。

または、数値164992818.48075795164,992,818.48075795として

printf/sprintf に追加する必要があるアポストロフィについて読みましたが、これは UNIX/POSIX のもののようで、私は Windows ユーザーです。

内部的に数値を文字列として出力するので、数値に応じてコンマを自動的に追加するカスタム実装を書くことができると思いました(> 1000> 10000> 100000など)が、strncpyのような機能に気付きましたまたは strcpy は、コンマを目的の位置に追加するのではなく、本質的に置き換えます。そして、これが私がそれを行う方法について振り出しに戻る方法です.

どうすればいいですか?

4

4 に答える 4

3

double 値を文字列に変換し、その文字列の各文字を調べてから、セパレータと共に出力文字列にコピーするには、実装が必要です。

このようなもの:

#include <stdio.h>
#include <string.h>

int thousandsep(double in, char* out_str, size_t out_len, unsigned int precision) {
    char in_str[128], int_str[128], format[32];
    size_t dlen, mod, i, j;
    int c;

    snprintf(format, sizeof format, "%%.%df", precision);
    snprintf(in_str, sizeof in_str, format, in);
    snprintf(int_str, sizeof int_str, "%d", (int)in);

    dlen = strlen(in_str);
    mod = strlen(int_str) % 3;
    c = (mod == 0) ? 3 : mod;

    for (i=0, j=0; i<dlen; i++, j++, c--) {
        if (j >= out_len - 1) {
            /* out_str is too small */
            return -1;
        }

        if (in_str[i] == '.') {
            c = -1;
        } else if (c == 0) {
            out_str[j++] = ',';
            c = 3;
        }

        out_str[j] = in_str[i];
    }
    out_str[j] = '\0';

    return 0;
}

次に、次のように使用します。

char out_str[64];

if (thousandsep(20043.95381376, out_str, sizeof out_str, 8) == 0)
    printf("%s\n", out_str);       /* 20,043.95381376 */

if (thousandsep(164992818.48075795, out_str, sizeof out_str, 8) == 0)
    printf("%s\n", out_str);       /* 164,992,818.48075795 */

if (thousandsep(1234567.0, out_str, sizeof out_str, 0) == 0)
    printf("%s\n", out_str);       /* 1,234,567 */

注: Windows を使用している場合は、MSVC を使用している可能性があるため、このソリューションは C89 コンパイラで動作するはずです。

于 2012-09-17T15:27:34.080 に答える
2

GetNumberFormatEx数値のプレーン文字列バージョンを取得し、グループ区切り記号、適切な小数点などでLOCALE_NAME_USER_DEFAULTフォーマットします。ロケールとして渡すと、ユーザーが好むフォーマットになります。

設定の 1 つ (精度など) をオーバーライドする必要がある場合は、NUMBERFMT 構造体にデフォルトを入力してから、制御する必要があるフィールドを変更できます。

于 2012-09-17T15:48:26.620 に答える
0

使用できるフォーマット ディレクティブがないようです。

以下は、浮動小数点数を含む文字列を取得し、適切な場所にコンマを挿入する手っ取り早い汚い方法です。

これは、いくつかの一時バッファーを使用します。桁区切り記号は、小数点記号と同様にロケールによって異なります。ただし、この例ではカンマがハードコーディングされています。

これは基本的に、浮動小数点数の文字列表現を取得し、数字を別のバッファーにコピーして、適切な場所にコンマを挿入するだけです。

私が言ったように、より少ないバッファでこれを行うことを検討することもできます.これは迅速で汚れており、非常に効率的ではありません.

{
    double dFloat = 123456789012.567890;
    char xBuff[128];
    sprintf (xBuff, "%f", dFloat);

    char xBuff2[128];
    int iLen = strlen(xBuff);
    int iPoint = iLen;
    for (iLen--; iLen >= 0; iLen--) {
        if (xBuff[iLen] == '.' || xBuff[iLen] == ',') {
            // found the decimal point.  depends on locale.
            iPoint = iLen;
            break;
        }
    }
    strcpy (xBuff2, xBuff + iPoint);   // save the decimal portion

    char xBuff3[128], xBuff4[128];
    xBuff3[127] = 0;    // set an end of string
    int  iCount, jLen;
    for (iCount = 1, jLen = 126, iLen--; iLen >= 0; jLen--, iLen--) {
        if ((iCount % 4) == 0) {
            xBuff3[jLen] = ',';
            jLen--;
            iCount = 1;
        }
        xBuff3[jLen] = xBuff[iLen];
        iCount++;
    }
    strcpy (xBuff4, xBuff3 + jLen + 1);
    strcat (xBuff4, xBuff2);
}
于 2012-09-17T15:12:59.940 に答える