@@ -59,13 +59,13 @@ public static <X> Specification<X> notEqual(String field, Double value, Double t
5959 return (root , cq , cb ) -> {
6060 Expression <Double > doubleExpression = getColumnPath (root , field ).as (Double .class );
6161 /**
62- * in order to be equal to doubleExpression, truncated value has to fit :
63- * value <= doubleExpression < value + tolerance
62+ * in order to be equal to doubleExpression, value has to fit :
63+ * value - tolerance <= doubleExpression < value + tolerance
6464 * therefore in order to be different at least one of the opposite comparison needs to be true :
6565 */
6666 return cb .or (
6767 cb .greaterThanOrEqualTo (doubleExpression , value + tolerance ),
68- cb .lessThan (doubleExpression , value )
68+ cb .lessThan (doubleExpression , value - tolerance )
6969 );
7070 };
7171 }
@@ -149,17 +149,18 @@ private static <X> Specification<X> appendNumberFilterToSpecification(Specificat
149149 return createNumberPredicate (specification , resourceFilter , value );
150150 }
151151
152- private static <X > Specification <X > createNumberPredicate (Specification <X > specification , ResourceFilterDTO resourceFilter , String value ) {
152+ private static <X > Specification <X > createNumberPredicate (Specification <X > specification , ResourceFilterDTO resourceFilter , String filterValue ) {
153153 // the reference for the comparison is the number of digits after the decimal point in filterValue
154- // filterValue is truncated, not rounded
155154 // extra digits are ignored, but the user may add '0's after the decimal point in order to get a better precision
156- String [] splitValue = value .split ("\\ ." );
155+ String [] splitValue = filterValue .split ("\\ ." );
157156 int numberOfDecimalAfterDot = 0 ;
158157 if (splitValue .length > 1 ) {
159158 numberOfDecimalAfterDot = splitValue [1 ].length ();
160159 }
161- final double tolerance = Math .pow (10 , -numberOfDecimalAfterDot ); // tolerance for comparison
162- Double valueDouble = Double .valueOf (value );
160+ // tolerance is multiplied by 5 to simulate the fact that the database value is rounded (in the front, from the user viewpoint)
161+ // more than 13 decimal after dot will likely cause rounding errors due to double precision
162+ final double tolerance = Math .pow (10 , -numberOfDecimalAfterDot ) * 0.5 ;
163+ Double valueDouble = Double .valueOf (filterValue );
163164 return switch (resourceFilter .type ()) {
164165 case NOT_EQUAL -> specification .and (notEqual (resourceFilter .column (), valueDouble , tolerance ));
165166 case LESS_THAN_OR_EQUAL ->
0 commit comments