x86 80-битный тип с плавающей точкой в Java
Я хочу эмулировать тип с повышенной точностью x86 и выполнять арифметические операции и приводить к другим типам в Java.
Я мог бы попытаться реализовать это, используя BigDecimal, но охват всех особых случаев вокруг NaN, бесконечности и приведений, вероятно, был бы утомительной задачей. Мне известны некоторые библиотеки, которые предоставляют другие плавающие типы с более высокой точностью, чем double, но я хочу иметь ту же точность, что и 80-битный float для x86.
Есть ли библиотека Java, которая обеспечивает такой тип с плавающей запятой? Если нет, можете ли вы предоставить другие советы, которые позволили бы реализовать такой тип данных с меньшими усилиями, чем придумать собственное решение BigDecimal?
3 ответа
80-битное значение лучше всего хранить как комбинацию long
(для мантиссы) и int
для экспоненты и подписать. Для многих операций, вероятно, будет наиболее целесообразно поместить верхнюю и нижнюю половину длинной в отдельные "длинные" значения, поэтому код для добавления двух чисел с совпадающими знаками и показателями, вероятно, будет выглядеть примерно так:
long resultLo = (num1.mant & 0xFFFFFFFFL)+(num2.mant & 0xFFFFFFFFL);
long resultHi = (num1.mant >>> 32)+(num2.mant >>> 32)+(resultLo >>> 32);
result.exp = num1.exp; // Should match num2.exp
if (resultHi > 0xFFFFFFFFL) {
exponent++;
resultHi = (resultHi + ((resultHi & 2)>>>1)) >>> 1; // Round the result
}
rest.mant = (resultHi << 32) + resultLo;
Немного неприятностей вокруг, но не совсем нереально. Ключ состоит в том, чтобы разбить числа на достаточно маленькие кусочки, чтобы вы могли выполнять всю свою математику как "long".
Кстати, обратите внимание, что если одно из чисел изначально не имело одинаковый показатель степени, необходимо будет отслеживать, выпали ли какие-либо биты с конца при смещении его влево или вправо в соответствии с показателем первого числа, поэтому чтобы иметь возможность правильно округлить результат после.
Если вы знаете, что ваш Java-код будет фактически выполняться на процессоре x86, реализуйте 80-битную арифметику в сборке (или C, если это поддерживает компилятор C) и вызовите ее с JNI.
Если вы нацелены на конкретную платформу, отличную от x86, посмотрите код qemu. Должен быть способ вырвать только ту часть, которая выполняет 80-битные операции с плавающей точкой. (Правка: реализация qemu - SoftFloat.). Позвони в JNI.
Если вы действительно хотите использовать кроссплатформенную 80-битную арифметику на чистой Java, вы все равно можете сравнить ее с реализацией C в эмуляторах ЦП с открытым исходным кодом, чтобы убедиться, что вы решаете правильные угловые случаи.
Это немного противоположно опции java strictfp, которая ограничивает вычисления до 8 байтов, где она делает 80 битов.
Итак, мой ответ - запустить JVM на 64-битной машине, может быть, в какой-то виртуальной машине с гипервизором / ОС, поэтому у вас есть платформа разработки.