Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using scientific notation in for loops

Tags:

c++

loops

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?

like image 284
Edmund Price Avatar asked Jun 20 '16 08:06

Edmund Price


People also ask

What are the rules of scientific notation?

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 ...

What is the difference between scientific notation and E-notation?

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 ...

What is a significant number in scientific notation?

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.

How many decimals are there in scientific notation?

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 ...


1 Answers

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.

like image 68
Bathsheba Avatar answered Sep 17 '22 22:09

Bathsheba