In Java there are nextUp() and nextDown() methods that return the next double (up or down) representable by the system.
It usually works on the binary representation of the double, just incrementing or decrementing a bit and getting back the double.
How can I implement methods that give the same results in dart?
One implementation of these methods in Java can be seen here: .base/share/classes/java/lang/Math.java
One explanation of some details of these methods can be seen here: /
In Java there are nextUp() and nextDown() methods that return the next double (up or down) representable by the system.
It usually works on the binary representation of the double, just incrementing or decrementing a bit and getting back the double.
How can I implement methods that give the same results in dart?
One implementation of these methods in Java can be seen here: https://github/openjdk/jdk/blob/master/src/java.base/share/classes/java/lang/Math.java
One explanation of some details of these methods can be seen here: https://www.geeksfeeks./java-math-nextup-method-examples/
Share Improve this question asked Feb 3 at 20:45 RseveroRsevero 3304 silver badges14 bronze badges2 Answers
Reset to default 1Heavily inspired by dart_numerics code:
static double nextUp(double x) {
if ((x.isNaN) || (x == double.infinity)) {
return x;
}
if (x == double.negativeInfinity) {
return -double.maxFinite;
}
if ((x == 0.0) || (x == -0.0)) {
return double.minPositive;
}
int signed64 = doubleToInt64Bits(x);
if (x > 0.0) {
signed64++;
} else {
signed64--;
}
return int64BitsToDouble(signed64);
}
static double nextDown(double x) {
if ((x.isNaN) || (x == double.negativeInfinity)) {
return x;
}
if (x == double.infinity) {
return double.maxFinite;
}
if ((x == 0.0) || (x == -0.0)) {
return -double.minPositive;
}
int signed64 = doubleToInt64Bits(x);
if (x > 0.0) {
signed64--;
} else {
signed64++;
}
return int64BitsToDouble(signed64);
}
static int doubleToInt64Bits(double value) {
ByteData bytes = ByteData(8);
bytes.setFloat64(0, value);
return bytes.getInt64(0);
}
static double int64BitsToDouble(int value) {
ByteData bytes = ByteData(8);
bytes.setInt64(0, value);
return bytes.getFloat64(0);
}
As a bonus I separated the doubleToInt64Bits() method so anybody wanting to work on a binary representation of doubles in Dart can use it in conjunction to int64BitsToDouble() already provided by dart_numerics.
As an extension to the other answer, here is a version without ByteData.getInt64
that will work on dart2js and Flutter Web. (The problem is that ByteData.getInt64
doesn't work when the Dart is compiled to Javascript.)
double nextUp(double x) {
if ((x.isNaN) || (x == double.infinity)) {
return x;
}
if (x == double.negativeInfinity) {
return -double.maxFinite;
}
if ((x == 0.0) || (x == -0.0)) {
return double.minPositive;
}
var (sign, exponent, precision) = doubleToComponents(x);
if (x > 0.0) {
precision++;
} else {
precision--;
}
return componentsToDouble(sign, exponent, precision);
}
double nextDown(double x) {
if ((x.isNaN) || (x == double.negativeInfinity)) {
return x;
}
if (x == double.infinity) {
return double.maxFinite;
}
if ((x == 0.0) || (x == -0.0)) {
return -double.minPositive;
}
var (sign, exponent, precision) = doubleToComponents(x);
if (x > 0.0) {
precision--;
} else {
precision++;
}
return componentsToDouble(sign, exponent, precision);
}
(int, int, int) doubleToComponents(double value) {
ByteData bytes = ByteData(8);
bytes.setFloat64(0, value);
final sign = bytes.getUint8(0) >> 7;
final exp = ((bytes.getUint8(0) & 0x7F) << 4) | ((bytes.getUint8(1) >> 4));
final prec = ((bytes.getUint8(1) & 0x0F) << 48) + (bytes.getUint32(2) << 16) + (bytes.getUint16(6));
return (sign, exp, prec);
}
double componentsToDouble(int sign, int exponent, int precision) {
ByteData bytes = ByteData(8);
bytes.setUint8(0, (sign << 7) + (exponent >> 4));
bytes.setUint8(1, ((exponent & 0xF) << 4) + (precision >> 48));
bytes.setUint32(2, (precision >> 16) & 0xFFFFFFFF);
bytes.setUint16(6, precision & 0xFFFF);
return bytes.getFloat64(0);
}