143

In code created by Apple, there is this line:

CMTimeMakeWithSeconds( newDurationSeconds, 1000*1000*1000 )

Is there any reason to express 1,000,000,000 as 1000*1000*1000?

Why not 1000^3 for that matter?

Laurel
  • 5,522
  • 11
  • 26
  • 49
Duck
  • 32,792
  • 46
  • 221
  • 426
  • 46
    Clarity and readability of the code. You can't put , or ' as separators in C, so the next best thing is computing the value from a multiplication. ^ is an unrelated operator in C - exclusive OR. – Iwillnotexist Idonotexist Nov 16 '16 at 13:21
  • 54
    it especially used for durations like : 2*60*60 .. its easy to notice that is for 2hours.. – Idali Nov 16 '16 at 14:41
  • 53
    For one I suspect 1,000,000,000 is not valid syntax – paparazzo Nov 16 '16 at 15:18
  • 2
    @Paparazzi Even if it was valid syntax, the syntax would have to be localized. In large parts of the world ',' is the decimal mark. – Taemyr Nov 16 '16 at 15:38
  • 15
    By the way, modern programming languages have alternative way to write the same, e.g. in Swift `1_000_000_000`. However, with time constants this is more difficult. It's more readable to write `30 * 60` (30 minutes in seconds) than to write `1800`. There are actually languages that will allow you to write units, e.g. `meters`, allowing you to protect yourself against bad assignments. – Sulthan Nov 16 '16 at 16:05
  • One more slight advantage of 1000*1000*1000 over 1000^3 (if power operator exists in language) is that it's easier to see order of magnitude quickly. – George Sovetov Nov 16 '16 at 18:20
  • 2
    For the same reason `1.0f / 255` is more readable than `0.0039215689f`. See this [post](http://stackoverflow.com/questions/22621241/what-does-the-constant-0-0039215689-represent). – ouah Nov 16 '16 at 18:20
  • Also, as a side note, if there of a lot of work with physical units, look for libraries which provide classes for units to write, for example, `1000 * Kilometers` or `15_min`. – George Sovetov Nov 16 '16 at 18:25
  • 29
    `^` is an XOR, not an exponent or power operator. – 3Dave Nov 16 '16 at 18:35
  • @DavidLively See [this comment](http://stackoverflow.com/questions/40633059/why-write-1-000-000-000-as-100010001000#comment68498749_40633059). – wizzwizz4 Nov 16 '16 at 18:39
  • 11
    @Paparazzi: In C++, `1,000,000,000` is valid syntax, and evalues to `0`. – Mooing Duck Nov 16 '16 at 21:22
  • 5
    as for me it's more comfortable to see 1e9 than 1000*1000*1000 :) – kot331107 Nov 16 '16 at 21:55
  • Are you asking about C or Objective C? – Ray Nov 16 '16 at 22:10
  • 1
    @kot331107: well but that would be a `double` literal, not an `int`. – Matteo Italia Nov 16 '16 at 22:48
  • @MatteoItalia uhm...so you can cast it to int in place if you need :) – kot331107 Nov 16 '16 at 23:28
  • 4
    `(1,000,000,000) == 0` – Mark K Cowan Nov 16 '16 at 23:48
  • 3
    @Paparazzi, @MooingDuck: C++ now supports `1'000'000`! – Ela782 Nov 17 '16 at 00:02
  • @kot331107 - You ever heard of rounding error? – Hot Licks Nov 17 '16 at 03:31
  • 1
    @Hot Licks C specifies the minimum precision and range of `double`. The `double` of @kot331107, `1e9`, is in range and exactly representable as a `double`, so no rounding error occurs when converting to a 32(plus)-bit integer. Larger values may have rounding issues. – chux - Reinstate Monica Nov 17 '16 at 04:24
  • 1
    FWIW, The gcc preprocessor will accept `#define BILLION 1000 ## 000 ## 000`, though the compiler won't accept `1000 ## 000 ## 000` as a literal. Not sure if this applies to objective-c or not. – Digital Trauma Nov 17 '16 at 05:17
  • Possible duplicate of [Representing big numbers in source code for readability?](http://stackoverflow.com/questions/14220217/representing-big-numbers-in-source-code-for-readability) – phuclv Nov 17 '16 at 07:06
  • related: [Why does the C parser not allow spaces between the digits of an integer literal?](http://stackoverflow.com/a/7696341/995714), [Why was the space character not chosen for C++14 digit separators?](http://stackoverflow.com/a/27768020/995714) – phuclv Nov 17 '16 at 07:08
  • @HotLicks rounding error with (int)1e9 ? – kot331107 Nov 17 '16 at 10:28
  • @kot331107 - Maybe not for that value, but if you habitually use the scheme you will get bit. – Hot Licks Nov 17 '16 at 12:53
  • @HotLicks Agree, but this certain value 1e9. – kot331107 Nov 17 '16 at 12:58
  • I like how Perl allows you to use `_` in numeric literal. `0x24_0000_0000` and `123_456` are perfectly legitimate literals in Perl. – ikegami Dec 06 '19 at 06:25
  • Related: [Why does long long n = 2000\*2000\*2000\*2000; overflow?](https://stackoverflow.com/q/66354756) – Peter Cordes Feb 25 '21 at 23:27

8 Answers8

203

One reason to declare constants in a multiplicative way is to improve readability, while the run-time performance is not affected. Also, to indicate that the writer was thinking in a multiplicative manner about the number.

Consider this:

double memoryBytes = 1024 * 1024 * 1024;

It's clearly better than:

double memoryBytes = 1073741824;

as the latter doesn't look, at first glance, the third power of 1024.

As Amin Negm-Awad mentioned, the ^ operator is the binary XOR. Many languages lack the built-in, compile-time exponentiation operator, hence the multiplication.

Laurel
  • 5,522
  • 11
  • 26
  • 49
Piotr Falkowski
  • 1,908
  • 1
  • 12
  • 23
  • 13
    And in languages that do have an exponentiation operator, it isn't necessarily '^'. In Fortran, for instance, it's '**'. – jamesqf Nov 16 '16 at 17:28
  • 4
    You should also include a link pointing to the important caveat, given in answer below, from @chux : http://stackoverflow.com/a/40637622/1841533 (especially as the OP tagged "c", which is very susceptible to this 'righ-hand side operation seem to have all terms limited to a smaller type, and therefore the multiplication may overflow' problem). https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow may help avoiding those in the general case? – Olivier Dulac Nov 16 '16 at 18:13
  • 4
    Also we should note that the computation is done at compile time. The C Standard requires the implementation to be able to compute constant expressions at compile-time for various features of the language and we can safely assume it is true when a constant expression is used like in this example. – ouah Nov 16 '16 at 18:32
  • 13
    Storing amount of memory as a double? That seems like a potential source of error. – JAB Nov 16 '16 at 19:25
  • [Here's a question I asked about the caret operator being chosen for XOR](http://softwareengineering.stackexchange.com/questions/331388/why-was-the-caret-used-for-xor-instead-of-exponentiation) that might explain a few things. – Qix - MONICA WAS MISTREATED Nov 16 '16 at 21:17
  • @JAB: All integer values up to and including 9,007,199,254,740,992 are precisely representable. Machines don't generally have that much memory yet, and if one considers hard drive space that's often allocated in chunks of 4096 bytes, so the number of such blocks in a machine with up to 36,893,488,147,419,103,232 bytes of storage. Perhaps some such machines exist, but they're certainly not commonplace as of 2016. – supercat Nov 16 '16 at 23:58
  • 7
    @supercat I'm aware of that, but by using double you could have a case where, say, you want a portion of the memory range, you divide by `x` to get the size of the subrange... and suddenly you have a fractional byte, which may require additional logic to compensate for. – JAB Nov 17 '16 at 00:00
  • @JAB "What, did you think we wanted full bytes? We only need a nybble or two." – Justin Time - Reinstate Monica Nov 17 '16 at 03:14
  • @PiotrFalkowski Note that C++11 has new syntax allowing the use of apostrophes to notate literals `1'000'000'000` – Humphrey Winnebago Nov 22 '19 at 23:45
  • 3
    Note however that `double storageBytes = 1024 * 1024 * 1024 * 1024;` will fail on most current hardware as the expression will cause arithmetic overflow. One would have to write `double storageBytes = 1024. * 1024 * 1024 * 1024;` – chqrlie Feb 02 '20 at 22:27
  • @chqrlie nstead of `double storageBytes = 1024. * 1024 * 1024 * 1024;` you may want to use hex float: `double memoryBytes = 0x1p40;` – phuclv Feb 25 '21 at 08:09
  • @phuclv: hex floats are a good and readable option to express simple multiples of powers of 2 on systems that support them. For powers of 10, `double storageBytes = 1e40;` is obvious. For other cases supporting `_` as a digit grouping character would be a simple extension, compatible with the C preprocessor, unlike the C++ single quote syntax `double storageBytes = 123_456_789_000.;` This syntax is very common in c-like languages such as java, javascript, etc. – chqrlie Feb 25 '21 at 12:29
73

Why not 1000^3?

The result of 1000^3 is 1003. ^ is the bit-XOR operator.

Even it does not deal with the Q itself, I add a clarification. x^y does not always evaluate to x+y as it does in the questioner's example. You have to xor every bit. In the case of the example:

1111101000₂ (1000₁₀)
0000000011₂ (3₁₀)
1111101011₂ (1003₁₀)

But

1111101001₂ (1001₁₀)
0000000011₂ (3₁₀)
1111101010₂ (1002₁₀)
Amin Negm-Awad
  • 15,951
  • 3
  • 33
  • 50
73

There are reasons not to use 1000 * 1000 * 1000.

With 16-bit int, 1000 * 1000 overflows. So using 1000 * 1000 * 1000 reduces portability.

With 32-bit int, the following first line of code overflows.

long long Duration = 1000 * 1000 * 1000 * 1000;  // overflow
long long Duration = 1000000000000;  // no overflow, hard to read

Suggest that the lead value matches the type of the destination for readability, portability and correctness.

double Duration = 1000.0 * 1000 * 1000;
long long Duration = 1000LL * 1000 * 1000 * 1000;

Also could simple use e notation for values that are exactly representable as a double. Of course this leads to knowing if double can exactly represent the whole number value - something of concern with values greater than 1e9. (See DBL_EPSILON and DBL_DIG).

long Duration = 1000000000;
// vs.
long Duration = 1e9;
Laurel
  • 5,522
  • 11
  • 26
  • 49
chux - Reinstate Monica
  • 113,725
  • 11
  • 107
  • 213
  • 5
    Very important remark ! https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow may help in a lot of cases? – Olivier Dulac Nov 16 '16 at 18:18
  • 2
    A `double` can exactly represent all integers up to 2^53 ≈ 9e15. – Edgar Bonet Nov 17 '16 at 09:56
  • 3
    @EdgarBonet True that [binary64](https://en.wikipedia.org/wiki/Double-precision_floating-point_format#IEEE_754_double-precision_binary_floating-point_format:_binary64) can represent whole number up to about 9e15. But C does not specify `double` use of binary64, even though it is very commonly used. Per the C spec, values up to 1e9 or so are exactly representable. It depends if you want to code to spec or rely on common practice. – chux - Reinstate Monica Nov 17 '16 at 15:14
  • @chux Why does 'long long Duration = 1 trillion' overflow if you get there with multiplication, but not otherwise? – patrick Nov 17 '16 at 18:12
  • 5
    @Patrick Both `1000` and `1000000000000` are _integer constants_. Each independently with have the type selected from `int`, `long` or `long long`. The compiler uses the first type of those 3 in which the _integer constant_ fits. `1000 * 1000 * 1000 * 1000` is done with `int` math as each `1000` in an `int`. The product overflows with 32-bit `int`. `1000000000000` is certainly representable as a `long long` (or possibly narrower) - no overflow. The type of the target `long long Duration` does not affect this "right side of the =" detemrination. – chux - Reinstate Monica Nov 17 '16 at 18:25
  • 3
    Placing the wider type first in the multiplication is important. With 16-bit `int`, `long x = 1000 * 1000 * 1000L;` would overflow, while `long x = 1000L * 1000 * 1000;` would not. – ad absurdum Jul 24 '17 at 15:03
51

For readability.

Placing commas and spaces between the zeros (1 000 000 000 or 1,000,000,000) would produce a syntax error, and having 1000000000 in the code makes it hard to see exactly how many zeros are there.

1000*1000*1000 makes it apparent that it's 10^9, because our eyes can process the chunks more easily. Also, there's no runtime cost, because the compiler will replace it with the constant 1000000000.

Tamás Zahola
  • 8,822
  • 4
  • 28
  • 44
  • 5
    FYI, there is a concept of digit separators that I learned about recently. Java has had it for a while now, and C# 7.0 may get it. I wish all languages would have this eye-candy feature. :) – iheartcsharp Nov 16 '16 at 15:40
  • 1
    Depending on the context using `1,000,000,000` wouldn't produce a syntax error, it would just mean something else. For example `CMTimeMakeWithSeconds( newDurationSeconds, 1,000,000,000 )` – Ross Ridge Nov 16 '16 at 18:15
  • 2
    @JMS10 C# already has it if you install VS15 preview version, can be written as `1_000_000_000` – user1306322 Nov 16 '16 at 19:08
  • 2
    Python is getting `_` as the separator, too :) – Wayne Werner Nov 16 '16 at 21:31
  • 2
    And C++ recently got the `'` separator, in C++14, so you can use `1'000'000'000`. (It was chosen because `1,000,000,000` could be misinterpreted as the comma operator or 4 distinct parameters, and `_1_000_000_000` is a valid (but probably bad) variable name.) – Justin Time - Reinstate Monica Nov 17 '16 at 03:29
27

For readability. For comparison, Java supports _ in numbers to improve readability (first proposed by Stephen Colebourne as a reply to Derek Foster's PROPOSAL: Binary Literals for Project Coin/JSR 334) . One would write 1_000_000_000 here.

In roughly chronological order, from oldest support to newest:

It's a relatively new feature for languages to realize they ought to support (and then there's Perl). As in chux@'s excellent answer, 1000*1000... is a partial solution but opens the programmer up to bugs from overflowing the multiplication even if the final result is a large type.

djechlin
  • 54,898
  • 29
  • 144
  • 264
  • Many modern programming languages have the same, e.g. Swift. Nothing new. – Sulthan Nov 16 '16 at 16:06
  • AFAIK, this comes from Perl. PL/M used $ for the same purpose, e.g: 0100$0010B – ninjalj Nov 17 '16 at 00:52
  • 1
    It *is* fairly new, though. The Java feature is perhaps 5 years old. Most other languages supporting this syntax are pretty new -- Swift itself is only a few years old. Python adds support in 3.6, which hasn't been released yet. – johncip Nov 17 '16 at 03:02
  • C++14 has this with `1'000000'000`. I find it most handy for writing constants in binary: `0b11'10'01'00` or something for a shuffle or blend control arg to an intrinsic. – Peter Cordes Nov 17 '16 at 04:06
  • @Air: See the revision history of this. It was a non-post. – Johannes Pille Nov 17 '16 at 10:00
  • 2
    Ada has supported underlines in integer literals for 33 years now. – Peter - Reinstate Monica Nov 17 '16 at 10:02
  • Python 3.6: 10\*\*9 or 1000\*\*3. Unless I missed some important update, numbers can only be digits. – Arthur Hv Nov 17 '16 at 10:02
  • Btw, I think writing `1000000000` or `1000*1000*1000` is equivalent in C, requiring the identical compile-time overflow diagnostics if applicable (a value within the type's representable values is a compile-time constraint for constants as well as for constant expressions). – Peter - Reinstate Monica Nov 17 '16 at 10:11
  • 1
    @djechlin: I've taken the liberty of adding more information, roughly in chronological order. I was mistaken before, judging by the Project Coin thread, Stephen Colebourne probably took the idea of underscore in integer literals from Fandom and/or Ruby. Ruby probably took the idea from Perl, and Perl from Ada. – ninjalj Nov 17 '16 at 19:27
  • Now that we're well past something that could be relegated to a comment, I retract all past comments and votes. The king is dead, long live the king! – Air Nov 17 '16 at 23:57
7

Might be simpler to read and get some associations with the 1,000,000,000 form.

From technical aspect I guess there is no difference between the direct number or multiplication. The compiler will generate it as constant billion number anyway.

If you speak about objective-c, then 1000^3 won't work because there is no such syntax for pow (it is xor). Instead, pow() function can be used. But in that case, it will not be optimal, it will be a runtime function call not a compiler generated constant.

Bista
  • 7,689
  • 3
  • 24
  • 52
Madars Vi
  • 652
  • 7
  • 10
4

To illustrate the reasons consider the following test program:

$ cat comma-expr.c && gcc -o comma-expr comma-expr.c && ./comma-expr
#include <stdio.h>

#define BILLION1 (1,000,000,000)
#define BILLION2 (1000^3)

int main()
{
        printf("%d, %d\n", BILLION1, BILLION2);
}
0, 1003
$
Peter - Reinstate Monica
  • 12,309
  • 2
  • 29
  • 52
0

Another way to achieve a similar effect in C for decimal numbers is to use literal floating point notation -- so long as a double can represent the number you want without any loss of precision.

IEEE 754 64-bit double can represent any non-negative integer <= 2^53 without problem. Typically, long double (80 or 128 bits) can go even further than that. The conversions will be done at compile time, so there is no runtime overhead and you will likely get warnings if there is an unexpected loss of precision and you have a good compiler.

long lots_of_secs = 1e9;
Laurel
  • 5,522
  • 11
  • 26
  • 49
jschultz410
  • 2,682
  • 11
  • 20