在 C/C++ 中将天文数字转换为人类可读的形式

发布于 2024-08-07 03:42:13 字数 249 浏览 7 评论 0原文

我的程序打印出巨大的数字 - 比如 100363443,高达一万亿 - 并且很难阅读它们,所以我想以易于阅读的形式打印任何数字。

现在我使用

printf ("%10ld", number);

格式

我希望使用 printf 得到结果数字。我的大部分代码是 C++ 但我不想引入 std::cout,因为我已经有了 printf

谢谢

My program prints out HUGE numbers - like 100363443, up to a trillion -- and it sort of hard to read them, so I would like to print any number in easy to read form.

right now I use

printf ("%10ld", number);

format

I would appreciate a resulting number using printf. Most of my code is c++ yet I don't want to introduce std::cout, as I already have printf

thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

烟火散人牵绊 2024-08-14 03:42:13

如果您有可用的选项并且不介意失去一点可移植性,请在 printf 格式字符串中使用非标准的撇号标志。

根据我的文档, ' 标志可用于 POSIX 系统自 1997 年以来。

如果您使用的是 Unix、Linux、Mac...,您应该没有问题
如果您使用的是 Windows、DOS、iSeries、Android...则一切皆有可能(但也许您可以在系统中安装 POSIX 层)。

#include <locale.h>
#include <stdio.h>

int main(void) {
  long int x = 130006714000000;

  setlocale(LC_NUMERIC, "en_US.utf-8"); /* important */
  while (x > 0) {
    printf("# %%'22ld: %'22ld\n", x); /* apostrophe flag */
    x *= 2; /* on my machine, the Undefined Behaviour for overflow
            // makes the number become negative with no ill effects */
  }
  return 0;
}

在我的系统上,该程序生成:

# %'22ld:    130,006,714,000,000
# %'22ld:    260,013,428,000,000
# %'22ld:    520,026,856,000,000
# %'22ld:  1,040,053,712,000,000
# %'22ld:  2,080,107,424,000,000
# %'22ld:  4,160,214,848,000,000
# %'22ld:  8,320,429,696,000,000
# %'22ld: 16,640,859,392,000,000
# %'22ld: 33,281,718,784,000,000
# %'22ld: 66,563,437,568,000,000
# %'22ld: 133,126,875,136,000,000
# %'22ld: 266,253,750,272,000,000
# %'22ld: 532,507,500,544,000,000
# %'22ld: 1,065,015,001,088,000,000
# %'22ld: 2,130,030,002,176,000,000
# %'22ld: 4,260,060,004,352,000,000
# %'22ld: 8,520,120,008,704,000,000

Use the non-standard apostrophe flag in the printf format string, if you have that option available and don't mind losing a little bit of portability.

According to my documentation, the ' flag is available for POSIX systems since 1997.

If you are on Unix, Linux, Mac, ... you should have no problem
If you are on Windows, DOS, iSeries, Android, ... all bets are off (but maybe you can install a POSIX layer to your system).

#include <locale.h>
#include <stdio.h>

int main(void) {
  long int x = 130006714000000;

  setlocale(LC_NUMERIC, "en_US.utf-8"); /* important */
  while (x > 0) {
    printf("# %%'22ld: %'22ld\n", x); /* apostrophe flag */
    x *= 2; /* on my machine, the Undefined Behaviour for overflow
            // makes the number become negative with no ill effects */
  }
  return 0;
}

On my system this program produces:

# %'22ld:    130,006,714,000,000
# %'22ld:    260,013,428,000,000
# %'22ld:    520,026,856,000,000
# %'22ld:  1,040,053,712,000,000
# %'22ld:  2,080,107,424,000,000
# %'22ld:  4,160,214,848,000,000
# %'22ld:  8,320,429,696,000,000
# %'22ld: 16,640,859,392,000,000
# %'22ld: 33,281,718,784,000,000
# %'22ld: 66,563,437,568,000,000
# %'22ld: 133,126,875,136,000,000
# %'22ld: 266,253,750,272,000,000
# %'22ld: 532,507,500,544,000,000
# %'22ld: 1,065,015,001,088,000,000
# %'22ld: 2,130,030,002,176,000,000
# %'22ld: 4,260,060,004,352,000,000
# %'22ld: 8,520,120,008,704,000,000
哽咽笑 2024-08-14 03:42:13

您可以使用 humanize_number() ,它使用 k、m 等后缀来省略低位数字。这不是标准例程,因此您应该下载我链接到的来源。 (2 条款 BSD 许可证,允许任何类型的使用。)

Humanize_number 手册页< /a>.

Humanize_number 源代码,来自 NetBSD

HUMANIZE_NUMBER(3)      NetBSD Library Functions Manual     HUMANIZE_NUMBER(3)

NAME
     dehumanize_number, humanize_number -- format a number into a human read-
     able form and viceversa

SYNOPSIS
     #include <stdlib.h>

     int
     dehumanize_number(const char *str, int64_t *result);

     int
     humanize_number(char *buf, size_t len, int64_t number,
         const char *suffix, int scale, int flags);

这是通过添加后缀来实现的,如下所示:

       Suffix    Description    Multiplier
       k         kilo           1024
       M         mega           1048576
       G         giga           1073741824
       T         tera           1099511627776
       P         peta           1125899906842624
       E         exa            1152921504606846976

You could use humanize_number() which uses suffixes like k, m, etc., to leave out low order digits. This is not a standard routine, so you should d/l the source I have linked to. (2-clause BSD license, allows any kind of use.)

Humanize_number man page.

Humanize_number source code from NetBSD.

HUMANIZE_NUMBER(3)      NetBSD Library Functions Manual     HUMANIZE_NUMBER(3)

NAME
     dehumanize_number, humanize_number -- format a number into a human read-
     able form and viceversa

SYNOPSIS
     #include <stdlib.h>

     int
     dehumanize_number(const char *str, int64_t *result);

     int
     humanize_number(char *buf, size_t len, int64_t number,
         const char *suffix, int scale, int flags);

This works by appending suffixes as follows:

       Suffix    Description    Multiplier
       k         kilo           1024
       M         mega           1048576
       G         giga           1073741824
       T         tera           1099511627776
       P         peta           1125899906842624
       E         exa            1152921504606846976
爱冒险 2024-08-14 03:42:13

简单的方法可能是在输出之前转换为双精度并使用 %e 这将以指数科学计数法打印它们。试试这个:

double n = (double)number;
printf("%10.0e", n);

Easy way might be to convert to a double just before output and use %e which will print them in exponential scientific notation. Try this:

double n = (double)number;
printf("%10.0e", n);
妄想挽回 2024-08-14 03:42:13
std::cout << std::setprecision(5) << std::scientific << 100363443.0;

请注意,该数字是一个浮点

编辑:或者如果您不喜欢科学,我在网上找到了这个:

struct comma : public std::numpunct<char>
{ 
    protected: std::string do_grouping() const { return "\003" ; } 
};

std::cout.imbue( std::locale( std::cout.getloc(), new comma ) );
std::cout << 100363443 << std::endl;

编辑2:正如杰瑞所指出的,您不需要上面的逗号类,这本身似乎就足够了(尽管可能有些语言环境根本不格式化大数字?):

std::cout.imbue( std::locale( "" ) );
std::cout << 100363443 << std::endl;
std::cout << std::setprecision(5) << std::scientific << 100363443.0;

note that the number is a float

EDIT: or if you don't like scientific I found this on the net:

struct comma : public std::numpunct<char>
{ 
    protected: std::string do_grouping() const { return "\003" ; } 
};

std::cout.imbue( std::locale( std::cout.getloc(), new comma ) );
std::cout << 100363443 << std::endl;

EDIT 2: As pointed out by Jerry you don't need the comma class as above, this seems sufficient by itself (although there are presumably locales which don't format large numbers at all?):

std::cout.imbue( std::locale( "" ) );
std::cout << 100363443 << std::endl;
苹果你个爱泡泡 2024-08-14 03:42:13

请记住本地化(特别是如果您正在编写库)。
在欧洲(英国除外),则为 1.000.000,而不是 1,000,000

Remember localization (especiallyif you are writing a library).
In europe (except the UK) it would be 1.000.000 rather than 1,000,000

赤濁 2024-08-14 03:42:13

这是我直接用 C 语言编写的一个示例,不使用语言环境。只对积极的一面起作用。 (来自“DiscoVlad”的帮助)

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <strings.h>


void my_reverse ( char* s ) {
    int c, i, j;
    for (i=0, j= strlen(s)-1;i<j;i++,j--) {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    }
}


char* insert_commas(unsigned long long input ) {
    int i, intlen;
    char* buffer;
    char* formatted;

    intlen = (int) ceil(log10(input * 1.0));
    buffer = (char *) malloc((intlen + 1) * sizeof(char));

    sprintf(buffer, "%llu", input);  // build buffer
    formatted = (char *) malloc((intlen + (int) ceil(intlen/3.0)) * sizeof(char));  // malloc output buffer
    my_reverse(buffer);

    for(i=intlen; i>=0; i--) {
        formatted[strlen(formatted)] = buffer[i];
        if (i%3 == 0 && i<intlen && i > 0) {
            formatted[strlen(formatted)] = ',';
        }
    }
    free(buffer);

    return formatted;
}


int main() {
    char* formatted;

    // don't forget to free(formatted) after each call.
    formatted = insert_commas(123);
    printf("output %s\n", formatted);
    // output 123

    formatted = insert_commas(1234);
    printf("output %s\n", formatted);
    // output 1,234

    formatted = insert_commas(123456);
    printf("output %s\n", formatted);
    // output 123,456

    formatted = insert_commas(1234567);
    printf("output %s\n", formatted);
    // output 1,234,567

    formatted = insert_commas(123456789);
    printf("output %s\n", formatted);
    // output 123,456,789

    formatted = insert_commas(12345678901234567890ull);
    printf("output %s\n", formatted);
    // output 12,345,678,901,234,567,890

}

Here is an example I wrote in straight C w/o using locale. Only works for positives. (Much help from "DiscoVlad")

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <strings.h>


void my_reverse ( char* s ) {
    int c, i, j;
    for (i=0, j= strlen(s)-1;i<j;i++,j--) {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    }
}


char* insert_commas(unsigned long long input ) {
    int i, intlen;
    char* buffer;
    char* formatted;

    intlen = (int) ceil(log10(input * 1.0));
    buffer = (char *) malloc((intlen + 1) * sizeof(char));

    sprintf(buffer, "%llu", input);  // build buffer
    formatted = (char *) malloc((intlen + (int) ceil(intlen/3.0)) * sizeof(char));  // malloc output buffer
    my_reverse(buffer);

    for(i=intlen; i>=0; i--) {
        formatted[strlen(formatted)] = buffer[i];
        if (i%3 == 0 && i<intlen && i > 0) {
            formatted[strlen(formatted)] = ',';
        }
    }
    free(buffer);

    return formatted;
}


int main() {
    char* formatted;

    // don't forget to free(formatted) after each call.
    formatted = insert_commas(123);
    printf("output %s\n", formatted);
    // output 123

    formatted = insert_commas(1234);
    printf("output %s\n", formatted);
    // output 1,234

    formatted = insert_commas(123456);
    printf("output %s\n", formatted);
    // output 123,456

    formatted = insert_commas(1234567);
    printf("output %s\n", formatted);
    // output 1,234,567

    formatted = insert_commas(123456789);
    printf("output %s\n", formatted);
    // output 123,456,789

    formatted = insert_commas(12345678901234567890ull);
    printf("output %s\n", formatted);
    // output 12,345,678,901,234,567,890

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文