Subrangetype for Double?

Hello :slight_smile:

what do you think about this Kind of datatype, or range-type?

TDoubleRange = 10.0 .. 45.5

Could this work?

Could be useful.

And then ofc, values under 10.0, even 9.9 and over 45.5 are not allowed.

–Shpend

This sounds like a great idea for a custom struct type? Not sure if this needs to be done on the compiler level.

But to be honest, your Argument would then also Count for the subrange-princips in General, which Pascal offers.

Those possibilities would be much better as a Compiler-Feature instead of own custum-type, because ist something really Abstract and not concrete, IMO

One potential problem I see that might arise with a floating point (FP) subrange is the age old problem of representation. It is possible (I think) that you might have a situation where an assignment to a subranged FP value is ostensibly in the valid, specified range but which actually falls outside of that range due to the internal representation being imprecise w.r.t the mathematically accurate value.

e.g. take a hypothetical situation where 10.0 cannot be exactly represented in double (it can, but let’s treat it as one of those cases which can’t). Let’s pretend that 10.0 in double is represented as 9.99999999999999… :

type
   MyDouble = 10.0 .. 45.5;

MyDouble x := 100 / 10;   // Actual value of x => 9.99999999999999999

What do you want the compiler behaviour to be in this case ?

Should the assignment fail with a range check error because the value is outside the specified range even though an inspection of the operands clearly shows that it should be within the required range, or should it be allowed because the actual subrange (as internally represented) is different than the specified subrange ?

You could extend the subrange syntax for FP types to include an epsilon specification, something along the lines of:

type
  MyDouble = 10.0..45.5 (0.001);

But you then need to ensure that any other operations involving comparisons of values of that type also respect that same epsilon consistently.

It would be cool if an epsilon specification could be applied by the compiler for us to all relevant operations, but this is perhaps not always desirable (sometimes you might want to do a precise comparison) and is clearly a more complex problem than simply adding support for subrange FP types.

Apart from anything else what would do you do if an expression involves FP values of types with differently specified epsilon ?

+0.02c

I guess if that were the case, both the value “10.0” and the bounds of the range would be represented as 9.9999999, so they’d match again ;).

Yes, they’d match (as per the second “what would you want the compiler to do?” Q that I posed).

But the behaviour would be in contradiction to the apparent specification in cases where an assignment is made that corresponds to the internal representation of the bounds of the range, rather than the numerically accurate value of that range.

x := 100 / 10;     
x := 9.9999999999999999999999999;  // i.e. the value corresponding to the internal 
                                   //  representation of the apparent subrange boundary

The first satisfies the lower bound of the subrange but in a potentially misleading manner - it appears to satisfy the 10.0 bound but actually has a lower value, as does the subrange itself. i.e. the actual value of the expression and the subrange are the same, despite not actually satisfying the specification of the subrange.

If this value were to then be passed into some method or process that further imposed an explicit range check using some technique other than naive comparison (perhaps expressly to avoid internal representation issues) then this seemingly correctly applied, compiler enforced subrange value might never-the-less fail other validation techniques applying superficially the same criteria.

The second also satisfies the lower bound of the subrange despite the very obvious appearance (according to inspection of the source/specification) that it does not.

There may also be cases where an expression with a value ostensibly just within a subrange has an internal representation that lies outside that subrange.

These may be highly unusual and rare edge cases, but the very fact that they exist is a compelling argument (imho) for not introducing such a thing to the compiler, at least not without formal epsilon support. But as noted, that itself would introduce further potential complications best avoided (also imho).

What is the benefit of a range of FP beside possible runtime range check?
And when range checks are disabled, we have nothing more than a normal FP.

What I think would really be nice to be able to define any range type, including a possible step, and be able to directly use it in a for each loop. Ex. in a way how it’s currently discussed in the C# community.