39

In languages that don't allow underscores in integer literals, is it a good idea to create a constant for 1 billion? e.g. in C++:

size_t ONE_BILLION = 1000000000;

Certainly, we shouldn't create constants for small numbers like 100. But with 9 zeros, it's arguably easy to leave off a zero or add an extra one in code like this:

tv_sec = timeInNanosec / 1000000000;
tv_nsec = timeInNanosec % 1000000000;
20
  • 25
    I hope everyone here votes for NO. That way, maybe one day my bank will transfer one billion dollars to my account because a programmer didn't use a constant and misplaced a zero! :)
    – Reactgular
    Commented May 24, 2013 at 16:30
  • 43
    Why not create constants for small numbers? What does 100 mean? Unless there is some context, it's a magic number.
    – Allan
    Commented May 24, 2013 at 16:30
  • 4
    @MathewFoscarini In general, mistakes can go either way. But when it comes to your bank, mistakes will always go against you.
    – emory
    Commented May 24, 2013 at 18:30
  • 23
    Consider writing 1e9, 10^9 or 1_000_000_000 if the language you are using supports it.
    – hammar
    Commented May 24, 2013 at 18:58
  • 6
    Long scale or short scale billion?
    – rvalue
    Commented May 26, 2013 at 6:42

13 Answers 13

34

Most languages feature some kind of exponential notation. A million is 1e6, (meaning 1 times 10 to the power of 6). This basically solves the issue even better than most propositions here.

In a lot of C-like languages, the scientific notation is however defining a floating point type, which is unfortunate if you really need an int. However, you can easily type-cast that constant to avoid implicit conversions in your formular.

n / int(1e9) would divide by a billion.

In your example, dealing with physical quantities (time in nanosecond), I would generally ask myself whether integer is the right type. In fact a floating point double might be better suited when dealing with measurable quantities (although there are of course cases where you would prefer a long long).

4
  • 6
    I think the NANOSECONDS_IN_ONE_SECOND solution is much clearer and neater Commented May 25, 2013 at 17:40
  • 1
    The Question was about integer liberals and I propose to use scientific notation. Whether to do this in place or by defining a constant is an issue of structuring code that was not asked for in the question. Defining a constant adds limited abstraction, I would write a conversion function/macro to achieve better abstraction
    – wirrbel
    Commented May 25, 2013 at 18:00
  • 1
    would casting a very large double to an int not risk the typical rounding difference problems of floating point numbers?
    – Philipp
    Commented May 26, 2013 at 12:11
  • with normal precision integer types this shouldnot be a problem as long as you use a double precision float to convert from. you are right when using values of the long long range.
    – wirrbel
    Commented May 26, 2013 at 12:50
146

Create one called NANOSECONDS_IN_ONE_SECOND instead as that what it represents.

Or a shorter, better name if you can think of one.

22
  • 58
    I'd say Nanoseconds_Per_Second but this is, in my opinion, the correct answer.
    – KChaloux
    Commented May 24, 2013 at 16:56
  • 8
    @Mathew I don't get your point. There's nothing wrong with saying millimeters per meter. You may be implying that it is redundant, in that nanosecond MEANS one billion fractions of a second, but there's nothing wrong in stating it again. It's like saying 1 + 1 = 2. "x per y" continues to make more sense when x and y are disjoint, like "units per half dozen" or "nanoseconds per millisecond" Commented May 24, 2013 at 17:34
  • 7
    @MathewFoscarini Actually, no, in this context it's not. If it were, a constant named NANOSECONDS is meaningless as you can't tell what it's supposed to apply to. Likewise, NANOSECONDS_PER_MICROSECOND is a similar valid constant that makes sense.
    – Izkata
    Commented May 24, 2013 at 17:41
  • 5
    @MathewFoscarini, "millimeters per meter" is a way to remove the unit on the conversion to get the raw value. 1mm/1m = 1000, which is exactly the point of what's being done here.
    – zzzzBov
    Commented May 24, 2013 at 19:48
  • 12
    Why so much typing? NS_PER_SEC should be obvious to anyone who ought to be dealing with nanoseconds.
    – Rex Kerr
    Commented May 24, 2013 at 21:03
67

Constants are meant to give numbers meaning. There is not any additional meaning in ONE_BILLION to 1000000000. Actually, it makes it more confusing, because in different natural languages, a billion means something different (either a thousand million or a million million)! If you want to write it shorter, there's a good chance your programming language allows the use scientific notation, i.e. 1e9. Otherwise, I agree with @JohnB, that this number really means the number of nanoseconds in a second, so name it that.

5
  • 10
    Good pointing that billion in different languages mean different amount of zeros.
    – frozenkoi
    Commented May 24, 2013 at 22:46
  • 3
    would suggest changing regular languages to natural languages. regular means something else...
    – jk.
    Commented May 25, 2013 at 6:39
  • Different interpretations of "billion" in languages such a good point! Why can't I upvote your answer twice!
    – Force444
    Commented May 25, 2013 at 13:10
  • 3
    You don't need different languages. You don't even need different countries. In British English, "billion" means something different before and after 1974 in official communications (mass media and government), and both usages still exist. Commented May 26, 2013 at 11:26
  • 1
    "There is not any additional meaning in ONE_BILLION to 10000000000.. I disagree. (Hint: I deliberately misquoted you and added another zero; would have have noticed if I hadn't mentioned it?) Commented Jun 3, 2013 at 19:41
26

For one or two usages, I would use the convention:

tv_sec = timeInNanosec / (1000 * 1000 * 1000);
tv_nsec = timeInNanosec % (1000 * 1000 * 1000);

It's perfectly self explanatory, gets compiled to a constant and it's hard to screw up.

Also, it's very useful in cases such as:

var Time = 24 * 60 * 60;

where it's easy to see we are talking about one day in seconds.

5
  • This is what I usually do. It also has the advantage that I won't forget that I defined NANOSECONDS_IN_ONE_SECOND yesterday and define NANOSECONDS_PER_SECOND today. And perhaps ONE_AMERICAN_BILLION tomorrow. Commented May 25, 2013 at 10:21
  • Surely 'SecondsInOneDay = 24 * 60 * 60' is easier still? Commented May 26, 2013 at 17:22
  • @JBRWilkinson sure, my initial snippet was using a class instance.Time = ..., but then I dumbed it down...
    – Sklivvz
    Commented May 26, 2013 at 20:29
  • 4
    In C or C++, (1000 * 1000 * 1000) is of type int, which is only required to be 16 bits, so it can overflow. You can write (1000L * 1000L * 1000L) to avoid that. Commented Jun 3, 2013 at 19:36
  • I do this a lot. It works very well.
    – vy32
    Commented Jun 11, 2013 at 15:13
10

The length of the value is not what defines whether a constant is needed or not.

You use constants to avoid magic numbers, not to avoid typing.

For example these are perfectly valid constants:

public static final int CLOSE_CURSORS_AT_COMMIT = 1;
public static final int CONCUR_READ_ONLY = 2;
public static final int CONCUR_UPDATABLE = 3;
public static final int FETCH_FORWARD = 4;
public static final int FETCH_REVERSE = 5; 
public static final int FETCH_UNKNOWN = 6;
public static final int HOLD_CURSORS_OVER_COMMIT = 7;
public static final int TYPE_FORWARD_ONLY = 8;
public static final int TYPE_SCROLL_INSENSITIVE = 9;
public static final int TYPE_SCROLL_SENSITIVE = 10;

Use:

public static final int NANOSECS_PER_SECOND = 1000000000;

(code samples are in Java, translate to your favorite language )

7
  • 3
    +1 Named numbers are nearly useless. The purpose of constants it to give meaning to those numbers. What do they represent? What thing are they counting or limiting or formally named coefficient? Not what is the value of the count.
    – JustinC
    Commented May 24, 2013 at 18:52
  • 5
    Seeing as we're talking Java, I'll make the observation that, as of Java 7, we can put underscores in numbers to help readability!
    – Nick
    Commented May 24, 2013 at 20:54
  • 2
    Those are terrible examples of valid constants. They should have been enums, except they were created before enums. Commented May 26, 2013 at 17:38
  • @ChristofferHammarström They were indeed created before enums, they are part of the ResultSet class, in the SQL package of the Java SDK. Commented May 26, 2013 at 20:39
  • 2
    @ChristofferHammarström They're bad because now we have enums but not for being unmeaningful. Enum didn't exist when these classes were created and in order to differentiate between mutually exclusive options like FETCH_FORWARD and FETCH_REVERSE is giving them a different value. The value doesn't matter, just the fact that they are different. Commented May 27, 2013 at 11:40
8

An American or European billion?

(or in technical terms, a billion in the short scale or long scale - one is 1000 million, the other is a million million).

Given this confusion, then I'd say yes - it makes sense to define it once and keep with it, likewise applies to any constant you need to agree the definition on - define it once.

3
  • 17
    "An American or European billion?" - "What? I don't know that! Ahhhhh!!!!"
    – Tesserex
    Commented May 25, 2013 at 0:01
  • In the UK, at least, we've long since adopted the 1e9 billion. Commented May 25, 2013 at 7:45
  • 1
    @Tesserex - well, you have to know these things when you're a king, you know.
    – gbjbaanb
    Commented May 25, 2013 at 12:51
6

Reasons Not To

Firstly, here is a reason not write any underscores or use any trick to simulate it: it makes the constants harder to find in the code. Suppose that some program exhibits, somewhere in its operation, hard-coded value 1500000 for some parameter. I want to know where in the source code of the program this actually occurs, so I grep the code for 1500000, and find nothing. Why? Might it be in hexadecimal (but why for such a round decimal number). Unbeknownst to me, the constant is actually written as 1_500_000. I needed the regex 1_?500_?000.

Guiding Characters in Comment

Just because one kind of visual aid is not available, or we don't wish to use it for the above reason, doesn't mean that we cannot take advantage of the two dimensions of the text file to create an alternative visual aid:

foo = bar / 1000000000;
//           --^--^--^  

With this we can easily convince ourselves that there are three groups of three zeros. Yet, we can still grep the source code for 1000000000 and find it.

Syntax Coloring

A text editor with programmable syntax coloring can be made to color groups digits in numeric constants with alternating colors for better readability. We don't have to do anything in the code.

Preprocessing: C, C++, Objective C

Now, if we really want some commas between digits, in C and C++ we can use some preprocessing:

/* Four digit base TH-ousand constant macro */
/* Condensed using Horner's rule */
#define TH(A,B,C,D) ((((((A) * 1000) + (B)) * 1000) + (C)) * 1000 + D)

tv_sec = nanoseconds / TH(1,000,000,000)

Works for numbers like TH(1,234,567,890).

A macro similar to TH can also work with token pasting rather than arithmetic. In the C preprocessor, the binary ## operator ("token paste") can be used in a macro body in order to paste together two operands into a single token. One or both of the operands can be macro arguments. The downside here (creating a risk for us) is that if the resulting catenation isn't a valid token, the behavior is undefined.

#define TOK4(A, B, C, D) A ## B ## C ## D

Now

TOK4(1,000,000,000)       /* produces the single token 1000000000 */
TOK4(1,123,000,000.0E+2)  /* produces the single token 1123000000.0E+2 */
TOK4(pr,in,t,f)           /* produces the token printf */
TOK4(#,*,a,b)             /* undefined behavior, #*ab is not valid token syntax */

C programs that paste together identifiers and use the results to name global variables and functions exist and are awful to work with because they are impervious to tools like GNU id-utils and ctags.

2
  • 2
    +1 for one of the best abuses of the preprocessor I've seen. I'd still go with NSEC_PER_SEC or something in production, though.
    – Victor
    Commented May 25, 2013 at 16:34
  • Very nearly -1 for abusing the preprocessor :)
    – user
    Commented May 26, 2013 at 14:11
3

Yeah, that sounds like a reasonable idea. Off-by-one DIGIT errors are even worse than the infamous off-by-one errors. Although, it may create confusion for other people (including your future self) to read the code.

A more explanatory name like NANOSEC_PER_SEC seems good, as it would add clarity where it is used for time. However, it makes no sense to use in contexts other than time, and it would be impractical to create a separate 1,000,000,000 for every situation.

What you really want to do, silly as it seems at first, is 'divide over sec'. This leaves NANO_PER, which is not only language-independent (10^9 in America and Europe) but also situation-independent (no limiting on the units), and it is easy to type and read.

1
  • this post is rather hard to read (wall of text). Would you mind editing it into a better shape?
    – gnat
    Commented May 24, 2013 at 21:12
3

In general it's a bad idea to use scalar constants for unit conversions, and if you find yourself making constants for such things you're doing conversion in way too many places.

When you have a quantity of one unit (say, 10 seconds), and want to convert to another unit (i.e. nanoseconds); this is precisely the time to use the type system of your language to ensure that the units are actually scaled as you intend.

Make your function take a Nanoseconds parameter, and provide conversion operators and/or constructors in that class for Seconds, Minutes, or what-have-you. This is where your const int or #define or 1e9 seen in other answers belongs.

This avoids having variables of ambiguous units floating around your code; and prevents entire swathes of bugs from where the wrong multiply/divide was applied, or was already applied, or the quantity was actually distance instead of time, or...

Also, in such classes it's good to make construction from plain scalarsprivate and use a static "MakeSeconds(int)" or similar to discourage sloppy use of opaque numbers.

More specifically to your example, in C++ check out Boost.Chrono.

1
  • 1
    + At the very least, use a common type with a scaling or offset factor from a basis, much like the often maligned timezone.
    – JustinC
    Commented May 26, 2013 at 8:50
1

I personally wouldn't consider it good practice to create a constant unless it needs to be a constant. If its going to be in multiple places and having it defined at the top of the file for modification / or testing is going to be useful then absolutely.

If its just because its awkward to type ? then no.

Personally if I got someone else's code that had a constant defined, I generally consider this to be an important aspect of the code. E.g. tcp keep alive timers, maximum number of connections allowed. If I had to debug it I would probably pay a lot of unneeded attention to it trying to figure out why / where its being used.

5
  • I get the joke but if bank programers had to make a constant for every number you could transfer the software would be gigantic, unmanageable and slow. I could only imagine what that would be like, imagine being told it would take 3 working days to transfer money to .... OH MY GOD, THATS IT!!! Commented May 24, 2013 at 17:08
  • My bank does take 3 days to transfer money :(
    – Reactgular
    Commented May 24, 2013 at 17:14
  • 1
    @MathewFoscarini bankers use Excel they do not need programmers ;)
    – Mateusz
    Commented May 24, 2013 at 17:44
  • @Simon Depending on language and compiler, constants should be optimized into the code, incurring little overhead. I understand your point, but constants can be used wherever using a name instead of a magic number would help code readability.
    – Steven
    Commented May 24, 2013 at 20:31
  • Awkward to read is much more of an issue than awkward to type.
    – Alb
    Commented May 24, 2013 at 23:13
0

When you think about why you wrote "1 Billion" instead of "1000000000" in your question title, you'll realise why the answer is yes.

0

Do not create a constant for your big literals. You would need a constant for each such literal, which is (in my opinion) a complete joke. If you desperately need to make your literals clearer without the help of things like syntax highlighting, you could (though I would not) create functions or macros to make your life "easier":

#define SPLIT3(x, y, z) x##y##z

int largeNumber1 = SPLIT3(123,456,789);
int largeNumber2 = 123456789;
0

I would do this:

const int Million = 1000 * 1000;
const int Billion = 1000 * Million;

or

const int SciMega = 1000 * 1000; const int SciGiga = 1000 * SciMega;

Regarding number of nanoseconds per second: nano is the "inverse" of giga.

Kilo  Mega  Giga   etc.
10^3  10^6  10^9
Milli Micro Nano   etc.
10^-3 10^-6 10^-9

Note the "Sci" - for scientific, as in computers, the meanings of kilo, mega, giga etc. are different: 1024 (2^10), 1024*1024 (2^20), etc. 2 megabytes is not 2,000,000 bytes.

UPDATE Commenter pointed out that special terms exist for digital exponents of 2: http://en.wikipedia.org/wiki/Mebibyte

5
  • "2 megabytes is not 2,000,000 bytes." Ask any spinning-platter hard disk manufacturer you want. (Not the downvoter, btw.)
    – user
    Commented May 26, 2013 at 14:13
  • @michaelkjorling this is a programming question, not a business ethics or marketing one. I do agree about hard drives, but that's a different topic. And ouch about the down votes!
    – Mr. TA
    Commented May 27, 2013 at 14:46
  • 1
    Actually, 2 Megabytes is 2,000,000 bytes. 2 Mebibytes is 2,097,152 bytes. See en.wikipedia.org/wiki/Mebibyte
    – vy32
    Commented Jun 11, 2013 at 15:14
  • @vy32 thanks, never heard of that before. Will update my answer to reflect that.
    – Mr. TA
    Commented Jun 11, 2013 at 17:14
  • @Mr.TA, no problem! We're working hard to bring Computer Science into compliance with SI Units! Join the club.
    – vy32
    Commented Jun 11, 2013 at 22:16

Not the answer you're looking for? Browse other questions tagged or ask your own question.