Negative values between -1 and 0
A value of -0.00412
40 we can use 0x40 xor 0x7f = 0x3f (which is the same exponent as for the positive value)
3C we can use 0x65 (101) – 0x3C = 0x29 (41)
51 we can use 0x65 (101) – 0x51 = 0x14 (20)
66 the minus sign
A value of -0.412
3f xor 7f = 40 (positive equivalent is 0xC0, highest bit differs) = -2
3c should be 41
51 should be 20
66
Seems to work.
+/- infinity
There is a byte array
FF
65
which is used for numbers larger than 9.999..9*10^125.
Smaller values then -9.999..9*10^125 will be stored as a single byte
00
Both values could be interpreted as +/- infinity.
Borders
Values with a smaller exponent than -130 will be stored as zero (one byte 0x80).
I have written the algorithms into a Java class:
import java.math.BigDecimal; import java.util.Arrays; public class OracleNumber { private final BigDecimal value; public static final OracleNumber ZERO = new OracleNumber(BigDecimal.ZERO); public static final OracleNumber POSITIVE_INFINITY = new OracleNumber(new BigDecimal("1E200")); public static final OracleNumber NEGATIVE_INFINITY = new OracleNumber(new BigDecimal("-1E200")); private OracleNumber(BigDecimal val) { this.value = val; } private OracleNumber(boolean negative, String mantissa, int exponent) { this.value = new BigDecimal((negative ? "-" : "") + mantissa + "0E" + exponent).stripTrailingZeros(); } private static boolean isZero(short[] array) { return array.length == 1 && array[0] == 0x80; } private static boolean isNegative(short[] array) { return ((array[0] & 0x80) == 0); } private static boolean hasPositiveExponent(short[] array) { return (array[0] & 0x40) != 0; } private static boolean isPositiveInfinity(short[] array) { return (array.length == 2 && array[0] == 0xFF && array[1] == 0x65); } private static boolean isNegativeInfinity(short[] array) { return (array.length == 1 && array[0] == 0x0); } public static OracleNumber newInstance(short[] array) { short[] number = Arrays.copyOf(array, array.length); if (isZero(number)) { return OracleNumber.ZERO; } if (isNegativeInfinity(number)) { return OracleNumber.NEGATIVE_INFINITY; } if (isPositiveInfinity(number)) { return OracleNumber.POSITIVE_INFINITY; } if (isNegative(number)) { // convert exponent into the equivalent for positive numbers number[0] = (short) ((number[0] | 0x80) ^ 0x7F); } int exponent; if (hasPositiveExponent(number)) { exponent = ((number[0] & 0x3F) << 1) - 2; } else { exponent = -1 * (((number[0] ^ 0xBF) << 1) + 4); } // calculating mantissa String mantissa = ""; for (int i = 1; i < number.length; i++) { if (isNegative(array)) { mantissa += (number[i] > 0x65) ? "" : (0x65 - number[i]); } else { mantissa += (number[i] - 1); } if (i == 1) { mantissa += "."; } } return new OracleNumber(isNegative(array), mantissa, exponent); } @Override public String toString() { return value.toString(); } public BigDecimal getValue() { return new BigDecimal(value.toString()); } }