number ranges

Ali Çehreli acehreli at yahoo.com
Thu Jan 20 16:33:20 UTC 2022


On 1/19/22 21:24, Salih Dincer wrote:

 > ```d
 >    size_t length() inout {
 >      //return last_ - first_ + 1 - empty_;/*
 >      auto len = 1 + last_ - first_;
 >      return cast(size_t)len;//*/
 >    }
 > ```

Good catch but we can't ignore '- empty_'. Otherwise an empty range will 
return 1.

 > But it only works on integers.

After fixing the size_t issue, it should work on user-defined types as 
well. In fact, it is better to leave the return type as auto so that it 
works with user-defined types that support the length expression but is 
a different type like e.g. MyDiffType.

Having said that, floating point types don't make sense with the 
semantics of a *bidirectional and inclusive* range. :) Let's see how it 
looks for ranges where the step size is 0.3:

import std.stdio;

void main() {
   float beg = 0.0;
   float end = 1.0;
   float step = 0.3;

   writeln("\nIncrementing:");
   for (float f = beg; f <= end; f += step) {
     report(f);
   }

   writeln("\nDecrementing:");
   for (float f = end; f >= beg; f -= step) {
     report(f);
   }
}

void report(float f) {
   writefln!"%.16f"(f);
}

Here is the output:

Incrementing:
0.0000000000000000
0.3000000119209290
0.6000000238418579
0.9000000357627869
                 <-- Where is 1.0?
Decrementing:
1.0000000000000000
0.6999999880790710
0.3999999761581421
0.0999999642372131
                 <-- Where is 0.0?

So if we add the 1.0 value after 0.9000000357627869 to be *inclusive*, 
then that last step would not be 0.3 anymore. (Thinking about it, step 
would mess up things for integral types as well; so, it must be checked 
during construction.)

The other obvious issue in the output is that a floating point iota 
cannot be bidirectional because the element values would be different.

Ali



More information about the Digitalmars-d-learn mailing list