在源代码中如何表示大数字以提高可读性?

28

在C++或C应用程序的源代码中,有没有更易读的方法来表示大数?

例如,我们拿数字2,345,879,444,641来说,如果我们想让程序返回这个数字,我们会写成return 2345879444641

但是这样并不易读。

例如,在PAWN(一种脚本语言)中,我可以写成return 2_345_879_444_641 或者 return 2_34_58_79_44_46_41,这两种方式都会返回数字2,345,879,444,641

对于人类来说,这样更容易阅读。

那么C++或C是否有类似的方法呢?


那我该如何表示286586837272呢?我想写成286_586_837_272的形式,1000000000000只是一个例子。 - user1182183
1
你想把任何数字以人类可读的形式呈现吗?我建议在注释中以任何你喜欢的格式添加它。 - im so confused
如果这是唯一可行的选项,那么好吧。 - user1182183
#define , `?哈哈哈,只有在其他地方不需要逗号时才可以这样做。这合法吗? - im so confused
2
请注意,游说已经在行动中:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3342.html - Marc Glisse
显示剩余3条评论
5个回答

37

使用当前编译器(C++14或更新版本),您可以使用撇号,例如:

auto a = 1'234'567;
如果你仍然使用C++11,你可以使用自定义字面量来支持类似这样的语法: int i = "1_000_000"_i。代码应该类似于:
#include <iostream>
#include <string>
#include <cstdlib>

int operator "" _i (char const *in, size_t len) { 
    std::string input(in, len);
    int pos;

    while (std::string::npos != (pos=input.find_first_of("_,"))) 
        input.erase(pos, 1);

    return std::strtol(input.c_str(), NULL, 10);
}

int main() { 
    std::cout << "1_000_000_000"_i;
}

我已经这样写了,支持下划线或逗号互换,所以你可以使用其中一种或两种。例如,"1,000_000"将变成1000000

当然,欧洲人可能更喜欢用 "." 代替 "," —— 如果是这样,请随意修改。


2
+1. 我正在写这个,但你已经完成了。这个解决方案唯一的问题是"1_000"_i不再是一个常量表达式! - Nawaz
+1对于无需使用boost库的方法,不过这是在运行时的解决方案,当然是个很好的解决方案,非常好,但如果能以预处理器的方式实现,那将是非常出色的。$ - user1182183
2
在C++14及更高版本中,对于撇号的使用应该加1。这个特性应该更加显眼,并且现在可能是最佳答案。 - Snackoverflow

13

使用Boost.PP

#define NUM(...) \
    NUM_SEQ(BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) 
#define NUM_SEQ(seq) \
    BOOST_PP_SEQ_FOLD_LEFT(NUM_FOLD, BOOST_PP_SEQ_HEAD(seq), BOOST_PP_SEQ_TAIL(seq)) 
#define NUM_FOLD(_, acc, x) \
    BOOST_PP_CAT(acc, x)

使用方法:

NUM(123, 456, 789) // Expands to 123456789

演示

另一种方法是创建 UDL。这里不再赘述(也因为需要更多代码)。


1
在这里发布使用示例,大多数人会感到困惑。 - Konrad Rudolph
是的,我只是想用自己编写的类似“printf”的函数来做到这一点... - dreamzor
这是一个非常好的解决方案!可能是C ++所能提供的最好的..希望能够支持1_000_000,但还不错,够用了:P - user1182183
使用Boost-任何东西可能比在您正在使用的编译器中修补词法分析器更加笨重...即使您需要对该词法分析器应用二进制补丁(例如,修补旧版本的VS C ++编译器以挖掘整数文字中的现代标点符号也不是非常困难)。 - Kuba hasn't forgotten Monica

7

这是一个宏,可以在MSVC和GCC上测试。不依赖于Boost...

#define NUM(...) NUM_(__VA_ARGS__, , , , , , , , , , )
#define NUM_(...) NUM_MSVCHACK((__VA_ARGS__))
#define NUM_MSVCHACK(numlist_) NUM__ numlist_
#define NUM__(a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, ...) a1_##a2_##a3_##a4_##a5_##a6_##a7_##a8_

使用方法如下:

int y = NUM(1,2,3,4,5,6,7,8);
int x = NUM(100,460,694);

生成:

int y = 12345678;
int x = 100460694;

好的,这很接近,没有预处理和提升。如果有人更接近"1_000_000",那么我会再次改变答案XD。 - user1182183
它是智能感知兼容的(Boost在智能感知上出现了“错误”,但可以编译)。 - user1182183

5

3
你可以使用一个预处理宏。
  #define BILLION (1000*1000*1000)

然后输入代码例如(4*BILLION);如果你关心2的大幂次方,只需使用1<<30

PS请注意,1e6是一个double文本(与1.0e6相同)

你也可以:

  1. 修补GCC词法分析器以接受数字文本的1_234_567表示法,并发布符合GPLv3和自由软件精神的补丁。
    可能在未来的GCC 4.8文件中的libpp/lex.cgcc/c-family/c-lex.c和/或gcc/cpp/lex.c中,即当前的主干。
  2. 游说C&C++标准化组,以使其被未来的C或C ++标准所接受。

这不仅仅是关于十亿,而是关于任何数字。 - user1182183
10
你可以写作 20亿+1300万+12万零789或类似的方式。 - Marc Glisse
2
将其设置为constexpr变量,也许也许也许,使用PP常量是不好的。 - Cat Plus Plus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接