user1182183
user1182183

Reputation:

Representing big numbers in source code for readability?

Is there a more human-readable way for representing big numbers in the source code of an application written in C++ or C?

let's for example take the number 2,345,879,444,641 , in C or C++ if we wanted a program to return this number we would do return 2345879444641.

But this is not really readable.

In PAWN (a scripting language) for example I can do return 2_345_879_444_641 or even return 2_34_58_79_44_46_41 and these both would return the number 2,345,879,444,641.

This is much more readable for the human-eye.

Is there a C or C++ equivalent for this?

Upvotes: 31

Views: 7389

Answers (5)

Jerry Coffin
Jerry Coffin

Reputation: 490108

With a current compiler (C++14 or newer), you can use apostrophes, like:

auto a = 1'234'567;

If you're still stuck with C++11, you could use a user-defined literal to support something like: int i = "1_000_000"_i. The code would look something like this:

#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;
}

As I've written it, this supports underscores or commas interchangeably, so you could use one or the other, or both. For example, "1,000_000" would turn out as 1000000.

Of course, Europeans would probably prefer "." instead of "," -- if so, feel free to modify as you see fit.

Upvotes: 39

Shafik Yaghmour
Shafik Yaghmour

Reputation: 158469

For C++1y you can now use single quote(') as a digit separator. Based on N3781: Single-Quotation-Mark as a Digit Separator which has finally been accepted. Both gcc and clang have supported this feature as part of their C++1y implementation.

So the following program (see it live for clang):

#include <iostream>

int main(){
    std::cout << 2'345'879'444'641 << std::endl ;
}

will output:

2345879444641

Upvotes: 7

JasonD
JasonD

Reputation: 16582

Here's a macro that would do it, tested on both MSVC and GCC. No reliance on 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_

Use it like:

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

Produces:

int y = 12345678;
int x = 100460694;

Upvotes: 8

You could use a preprocessor macro

  #define BILLION (1000*1000*1000)

then code e.g. (4*BILLION) ; if you care about large power of two just ust 1<<30

PS Notice that 1e6 is a double literal (same as 1.0e6)

And you could also:

  1. patch the GCC lexer to accept 1_234_567 notation for number literals and publish that patch for conformance with GPLv3 and free software spirit.
    probably in file libpp/lex.c and/or gcc/c-family/c-lex.c and/or gcc/cpp/lex.c of future GCC 4.8, i.e. current trunk.
  2. lobby the C & C++ standardization groups to get that accepted in future C or C++ standards.

Upvotes: 3

Cat Plus Plus
Cat Plus Plus

Reputation: 129764

With 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)

Usage:

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

Demo.

Another way is making an UDL. Left as an exercise (and also because it requires more code).

Upvotes: 13

Related Questions