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
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
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
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
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
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
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
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
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
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
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
When you think about why you wrote “1 Billion” instead of “1000000000” in your question title, you’ll realise why the answer is yes.
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;
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