【问题标题】:Is there a way to write a large number in C++ source code with spaces to make it more readable? [duplicate]有没有办法在 C++ 源代码中用空格编写大量数字以使其更具可读性? [复制]
【发布时间】:2018-11-06 15:35:51
【问题描述】:

假设我有代码:

vector<int> temp = vector<int>(1 000 000 000);

上面的内容不会编译,因为编译器会抱怨空格。是否可以指示 C++ 在编译时省略这些空格,或者以其他方式使数字更易于阅读?

【问题讨论】:

  • Relevant post(因为在道德上写这样一个数字的最佳方式显然是1e9)。
  • 当然analog literals 是最容易阅读的选项
  • @Rakete1111 它是重复的,但是如果您在此处看到接受的答案,数字分隔符不是原始问题中的答案之一,因此我的问题提供了更新。
  • 嗯,但它是??
  • 啊,在底部,nvm

标签: c++ syntax numbers


【解决方案1】:

试试数字分隔符:

int i = 1'000'000'000;

此功能由since C++14 引入。它使用单引号 (') 作为数字分隔符。


另见:

【讨论】:

  • 它也适用于其他基地。十六进制:0x01'ff,八进制:0'777,二进制:0b0000'1111'0000 :)
  • @Nicky C 仅此答案就有大约三分之一的分数,太好了!
【解决方案2】:

当我在没有 C++14 的平台上(通常用于微处理器)上做类似的事情时,我通过乘法将其拆分来表示大数:

int i = (1000 * 1000 * 1000);

添加ULL 后缀来品尝

这里的优点是它基本上兼容任何支持 C89(可能更早)的平台。

通常,假设乘法运算符会在编译时失效可能是安全的,但如果您在循环中使用这样的常量,则可能值得仔细检查。

【讨论】:

  • 这在具有 16 位 int 的系统上无法正常工作。同样,虽然1000'000'000'000(或没有's)会在32 位-int 系统上为您提供long long,但您的1000*1000*1000*1000 方法将由于溢出而产生UB。您需要使用 long long 文字,例如1000LL*1000*1000*1000.
  • 这似乎是一种可疑的技术。乘法不是一个“慢”运算符,具有高延迟和低吞吐量吗?
  • @Galaxy - 请参阅有关编译时乘法失败的说明。
【解决方案3】:

我通常为此目的#define 常量,因为它可以节省计数零,并让查看代码的人非常清楚你的意思。例如

#define THOUSAND 1000
#define MILLION 1000000

vector<int> temp = vector<int>(THOUSAND * MILLION);

这清楚地表明我的意思是一亿,并没有算错零

如果您愿意,显然可以使用枚举。

【讨论】:

  • 对于任何对“千百万”而不是“十亿”的选择感到好奇的人——"billion" doesn't always mean 1e9。通常最好使用明确的(如果稍微考虑一下)术语,因为这会让人们不会想知道为什么他们的值会相差几个数量级,甚至可能是“随机的”,因为它们正在包装。
  • 如果您的同事离开开放会话,请替换为 #define MILLION 100000。 :)
  • @ctrl-alt-delor 这更好:youtube.com/watch?v=C-52AI_ojyQ
【解决方案4】:

另一个想法可能是:

#define _000 *1000

int k = 1 _000 _000;

【讨论】:

  • 喜欢最佳答案?有什么问题?
  • int k = 2 _000 _000 / 1 _000;将 i 设置为 20 亿,而不是 2000。
  • 哦,很好。也许 (2 _000 _000) / (1 _000) ..... 虽然如果 C++14 可用,2'000'000 / 1'000 会好很多。
  • 你是对的。但有时我只有旧的 C++ 编译器(遗留代码);)
【解决方案5】:

如果您不使用 C++14,另一种选择是使用某种类型的字符串继承类,该类具有隐式 int-cast,并且可能在构造函数中使用正则表达式检查来限制数字。 我用 CString 作为一个简单的例子。

class NumString : public CString
{
public:
    NumString(CString number) : num(number) { } //maybe insert some regex-check here
    operator long() const
    {
        CString tmp = num;
        tmp.Remove(' ');        
        return atol(tmp);
    }
private:
    CString num;
};


NumString a = "1 000 000 000";
int b = a;
bool test = b == 1000000000;
//test will be true

【讨论】:

  • 在运行时解析编译时已知的值是一个丑陋的想法。
【解决方案6】:

这让我想起了我的第一个没有 C++14 的笨拙方法
会是

#define INTGROUPED1(a)     (a%1000)
#define INTGROUPED2(a,b)   (a%1000*1000 + b%1000)
#define INTGROUPED3(a,b,c) (a%1000*1000000 + b%1000*1000 + c%1000)
int v1 = INTGROUPED1(        123);
int v2 = INTGROUPED2(    123,123);
int v3 = INTGROUPED3( 23,123,123);

但我宁愿在私人环境中使用这些技巧。

想想有人写作

INTGROUPED3(1234,1234,1234); //This would be (234,234,234) without a compiler complaining

EDIT1:

也许更好的方法是使用 ## 预处理器操作符

#define NUM_GROUPED_4ARGS(a,b,c,d) (##a##b##c##d)
int num = NUM_GROUPED_4ARGS(-2,123,456,789); //int num = (-2123456789);

这更像是所见即所得,但不能免于误用。例如。你可能希望编译器抱怨

int num = NUM_GROUPED_4ARGS(-2,/123,456,789);  //int num = (-2/123456789); 

但它不会。

【讨论】:

  • 我能以某种方式理解我的第一种方法的反对意见(我自己表示它是头脑风暴,称它为笨拙),但至少它是第一个非 C++14 方法,而无需#define 宏每个数字
  • 这是一个有趣的开箱即用解决方案。我喜欢你实际上可以使用逗号作为分隔符。使用预处理器元编程,您可以创建一个可变参数宏,例如 NUM_GROUP(123,456,789),它适用于任意数量的组。无论如何,我实际上不会在实际代码中使用该技术,但这是一个很好的实验。
猜你喜欢
  • 2012-06-14
  • 2011-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-21
相关资源
最近更新 更多