I've recently come across some code which has a loop of the form
for (int i = 0; i < 1e7; i++){ }
I question the wisdom of doing this since 1e7 is a floating point type, and will cause i
to be promoted when evaluating the stopping condition. Should this be of cause for concern?
Scientific Notation Rules 1 If the given number is multiples of 10 then the decimal point has to move to the left, and the power of 10 will be... 2 If the given number is smaller than 1, then the decimal point has to move to the right, so the power of 10 will be... More ...
Below is a comparison of scientific notation and E-notation: Scientific notation E-notation 5 × 10 0 5E0 7 × 10 2 7E2 1 × 10 6 1E6 4.212 × 10 -4 4.212E-4 1 more rows ...
Under scientific notation, any number is written such that its value lies between the numbers 1 and 10, not including 10 but including 1. Where n is a real number such that 1 ≤ n < 10 and is known as the significant. The starting point should always be ten.
Scientific notation Decimal notation Scientific notation 5 5 × 10 0 700 7 × 10 2 1,000,000 1 × 10 6 0.0004212 4.212 × 10 -4 1 more rows ...
The elephant in the room here is that the range of an int
could be as small as -32767 to +32767, and the behaviour on assigning a larger value than this to such an int
is undefined.
But, as for your main point, indeed it should concern you as it is a very bad habit. Things could go wrong as yes, 1e7 is a floating point double type.
The fact that i
will be converted to a floating point due to type promotion rules is somewhat moot: the real damage is done if there is unexpected truncation of the apparent integral literal. By the way of a "proof by example", consider first the loop
for (std::uint64_t i = std::numeric_limits<std::uint64_t>::max() - 1024; i ++< 18446744073709551615ULL; ){ std::cout << i << "\n"; }
This outputs every consecutive value of i
in the range, as you'd expect. Note that std::numeric_limits<std::uint64_t>::max()
is 18446744073709551615ULL
, which is 1 less than the 64th power of 2. (Here I'm using a slide-like "operator" ++<
which is useful when working with unsigned
types. Many folk consider -->
and ++<
as obfuscating but in scientific programming they are common, particularly -->
.)
Now on my machine, a double is an IEEE754 64 bit floating point. (Such as scheme is particularly good at representing powers of 2 exactly - IEEE754 can represent powers of 2 up to 1022 exactly.) So 18,446,744,073,709,551,616
(the 64th power of 2) can be represented exactly as a double. The nearest representable number before that is 18,446,744,073,709,550,592
(which is 1024 less).
So now let's write the loop as
for (std::uint64_t i = std::numeric_limits<std::uint64_t>::max() - 1024; i ++< 1.8446744073709551615e19; ){ std::cout << i << "\n"; }
On my machine that will only output one value of i
: 18,446,744,073,709,550,592
(the number that we've already seen). This proves that 1.8446744073709551615e19
is a floating point type. If the compiler was allowed to treat the literal as an integral type then the output of the two loops would be equivalent.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With