As pkpnd stated in their comment, there is a known difference between one int and the next (ex. 4 and 5 are one integer apart). However, how far apart are two arbitrary doubles, an ulp?

One suggestion that I have to emulate a range is to use a NavigableMap:

enum Range {
    LIGHT, MODERATE, VIGOROUS, UNKNOWN
}

NavigableMap<Double, Range> map = new TreeMap<>();

map.put(Double.NEGATIVE_INFINITY, Range.UNKNOWN);
map.put(0D, Range.LIGHT);
map.put(3D, Range.MODERATE);
map.put(6D, Range.VIGOROUS);

System.out.println(map.floorEntry(4D).getValue());

Output:

MODERATE

You're free to handle out-of-range values however you'd like, as well a Double.NaN.

Answer from Jacob G. on Stack Overflow
Top answer
1 of 2
1

I fully concur with @TimothyTruckle on format, follow his advice.


Using binaries is restrictive (only two states), and not user-friendly. I don't like byte arithmetics, its quite un-Java like. I suppose you come from C/C++ background.

In more Java-like syntax, I propose a fluent interface on a Range class:

public class Range {

     private static enum RangeType{ INCLUSIVE, EXCLUSIVE, INFINITE };

     private static class RangeStart {
         private final RangeType startType;
         private final Double startValue;
         private RangeStart(RangeType type, Double value){
             this.startType = type;
             this.startValue = value;
         }
         public Range toInclusive(double endValue) {
              // Optionally check endValue >= startValue and throw something
              return new Range(startType, startValue, RangeType.INCLUSIVE, endValue);
         }
         public Range toExclusive(double endValue) {
              // Optionally check endValue >= startValue and throw something
              return new Range(startType, startValue, RangeType.EXCLUSIVE, endValue);
         }
         public Range toInfinity() {
              return new Range(startType, startValue, RangeType.INFINITY, 0.);
         }
     }

     public static RangeStart fromInfinity() {
          retur new RangeStart(RangeType.INFINITY, 0.)
     }

     public static RangeStart fromInclusive(double fromValue) {
          retur new RangeStart(RangeType.INCLUSIVE, fromValue)
     }

     public static RangeStart fromExclusive(double fromValue) {
          retur new RangeStart(RangeType.EXCLUSIVE, fromValue)
     }

     private final RangeType startType;
     private final Double startValue;
     private final RangeType endType;
     private final Double endValue;

     private Range(RangeType startType, Double startValue, RangeType endType, Double endValue) {
          this.startType  = startType;
          this.startValue = startValue;
          this.endType    = endType;
          this.endValue   = endValue;
     }

     public boolean contains(double value){
          // Do your thing here, I'm not doing all the work! ;-)
     }
}

This creates a re-usable Range object to check values. The Pattern used is similar to the Builder Pattern (I named the Builder RangeStart).

Example usage:

Range range5i7e = Range.fromInclusive(5).toExclusive(7);
range5i7e.contains(5); // true
range5i7e.contains(5); // false
Range.fromInclusive(-10).toInfinity().contains(3720); // true    Range.fromInclusive(5).toExclusive(3); // Throws something ?

Style improvements:

You may want to make inclusive the standard and use Range.from(1).to(2) to make a closed Range. It's much less verbose.

You could also make the Range infinite-ended on both sides unless otherwise told, like Range.to(5) would be ]Inf, 5] etc.

2 of 2
1

Should I throw exceptions if range_a is less than range_b?

This depends on your requirements. - Does the user of this function have to provide the input in correct order because a wrong order is a follow up of serious problem in her preceding code? Then you should throw an exception and this might even be a checked custom type to make the user aware of it. - Or is the wrong order something that is likely to happen and no problem outside your method? The reordering and going on inside your method is appropriate.

Should I throw exceptions if range_a is less than range_b?

This also must be specified by the requirements. If there was no requirement add a Javadoc comment explaining that and why you (not) return true in this situation.

I'm using camelcase for methods and variables

as expected by the java naming conventions.

Underscore is used to show that values are connected. and used together:
Example: pos_x, pos_y or range_a, range_b

Why not posX, posY and rangeX, rangeY

or even better: since Java is an object oriented language, why not using objects to group things that belong together?

class Tupel {
  long a,b;
  Tupel(int a, int b){
    this.a = a;
    this.b = b;
  }
}

Tupel pos = new Tupel(10,30);
Tupel range = new Tupe(5,59);
// ...
if (range.a > range.b) {
  range = new Tupel(range.b,range.a);
// ...

Why isn't checkMode an enumeration? – Alexander

The good thing about Java enums is that they can hold logic. The enum constants are classes that extend the enum class. This way enums can improve your code by resolving if/else cascades or switch constructs with polymorphism.

You don't need to access the enum's raw values.[...] – Alexander

With that in mind you have only 2 enum constants

enum CompareMode{
  RANGE_EXCLUSIVE{
    @Override
    protected abstract boolean isInRange(long value, long range_a, long range_b){
      return value > range_a && value < range_b;
    }
  },
  RANGE_INCLUSIVE{
    @Override
    protected abstract boolean isInRange(long value, long range_a, long range_b){
      return value >= range_a && value =< range_b;
    }
  };
  public boolean inRange(long value, long range_a, long range_b){
     if(range_a > range_b)
       return isInRange( value,range_b,range_a);
     else // <- not needed but her for readability
       return isInRange( value,range_a,range_b);       
  };
}

you complete logic is inside the enum, no extra method needed.


Now lets join that with the Tupel class:

enum CompareMode{
  RANGE_EXCLUSIVE{
    @Override
    protected abstract boolean isInRange(long value, Tupel range){
      return value > range.a && value < range.b;
    }
  },
  RANGE_INCLUSIVE{
    @Override
    protected abstract boolean isInRange(long value, Tupel range){
      return value >= range.a && value =< range.b;
    }
  };
  public boolean inRange(long value, Tupel range){
     if(range.a > range.b)
       range=new Tupel(range.b,range.a);
     return isInRange( value,range_a,range_b);       
  };
}

The benefit of that solution is:

  • the parameter list is shorter and has no more possibility to mix the values passed in accidentally.
  • if you later add another CompareMode (which is hard to imaging, but try...) the only thing you have to change is the lines for the new mode and the code where you decide which mode to use. The code that actually needs the result does not need to change.

Also, how are you calling methods in enum? – Michael

like this:

   Tupel range = new Tupel(4,5);
   for(CompareMode compareMode : CompareMode.values()){
    System.out.println(4+" is in range with compareMode "+compareMode +" ="+compareMode.inRange(4,range);
    System.out.println(5+" is in range with compareMode "+compareMode +" ="+compareMode.inRange(5,range);
   }
🌐
Quora
quora.com › What-is-the-range-of-the-double-data-type-in-Java
What is the range of the double data type in Java? - Quora
Answer (1 of 4): The range of double in Java is 1.7976931348623157 x 10^308 to 4.9406564584124654 x 10^-324. The java documentation mentions all such details of different data types and all the classes, interfaces and function that are shipped ...
🌐
Apache Commons
commons.apache.org › proper › commons-lang › javadocs › api-2.4 › org › apache › commons › lang › math › Range.html
Range (Commons Lang 2.4 API)
Gets the maximum number in this range as a double. This implementation uses the getMaximumNumber() method. Subclasses may be able to optimise this. Returns: the maximum number in this range · public float getMaximumFloat() Gets the maximum number in this range as a float.
🌐
TheServerSide
theserverside.com › blog › Coffee-Talk-Java-News-Stories-and-Opinions › Java-double-precision-2-decimal-places-example-float-range-math-jvm
Java double decimal precision
The precision of a double in Java is 324 decimal places. But the Java double isn't always as precise as you think it should be. Sometimes even simple, two decimal Java double calculations yield ...
Find elsewhere
🌐
Programming.Guide
programming.guide › java › double-range.html
Java: Range of a double | Programming.Guide
In Java, a double is a 64-bit IEEE 754 floating point. Double values are symmetrical around origo and has a maximum magnitude of 1.7976931348623157e308
🌐
Apache Commons
commons.apache.org › proper › commons-lang › apidocs › org › apache › commons › lang3 › DoubleRange.html
DoubleRange (Apache Commons Lang 3.20.0 API)
Specializes NumberRange for Doubles. This class is not designed to interoperate with other NumberRanges ... Fits the given value into this range by returning the given value or, if out of bounds, the range minimum if below, or the range maximum if above.
🌐
Baeldung
baeldung.com › home › java › java numbers › float vs. double in java
Float vs. Double in Java | Baeldung
January 4, 2025 - This test demonstrates that values exceeding the precision limit of float are truncated, while double maintains accuracy up to 15 digits and rounds beyond that. The delta of 1e-15 accounts for minor rounding differences in double precision.
🌐
TheServerSide
theserverside.com › blog › Coffee-Talk-Java-News-Stories-and-Opinions › Float-vs-Double-Whats-the-difference
Java double vs float: What's the difference?
From the output of the program above, we see the size difference between float and double Java types is: The upper range of a double in Java is 1.7976931348623157E308.
🌐
Coderanch
coderanch.com › t › 368695 › java › Range-Data-Type-double
Range of Data Type double (Java in General forum at Coderanch)
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums · this forum made possible by our volunteer staff, including ... ... As per the Book, long Data Types Range is -9223372036854775808 to 9223372036854775807.
🌐
Baeldung
baeldung.com › home › java › java numbers › check if a double is an integer in java
Check if a double Is an Integer in Java | Baeldung
January 24, 2024 - In this test, we assign 2.0D * Integer.MAX_VALUE to the double d3. Obviously, this value is a mathematical integer but out of Java’s integer range.
🌐
DataCamp
datacamp.com › doc › java › double
double Keyword in Java: Usage & Examples
The range for double values is approximately from 4.9e-324 to 1.7e+308. ... public class DoubleExample { public static void main(String[] args) { double pi = 3.14159; double gravity = 9.81; System.out.println("Value of pi: " + pi); System.out.println("Value of gravity: " + gravity); } }