Согласно документации Matlab, когда Java-метод возвращает long
, он преобразуется в double
перед назначением в Matlab.
Точность была потеряна. Меня интересуют более низкие цифры long
, возвращаемые методом Java. A double
не может представлять их, но Matlab int64
может. (Это понятно, учитывая, что оба типа имеют 64 бита, а double
использует некоторые из них для представления экспоненты.)
Если бы я имел контроль над Java-кодом, я мог бы вернуть массив с одним элементом, содержащий long
- в этом случае Matlab сохраняет их как int64
s, но в моем случае я вызываю библиотечную функцию.
В настоящее время лучшим способом я могу написать обертку в Java, которая вызовет метод и вернет ответ в массиве. Но с этим подходом есть проблемы с переносимостью. Есть ли лучший способ?
В комментариях был дан ответ, но только для полноты, лучший способ получить Java long
в Matlab как int64
невредим, похоже, пишет небольшую оболочку Java, которая вызывает любой метод, который у вас есть, и возвращает ответ в long[]
.
(Если код должен быть распространен, подумайте о компиляции этого класса Java с целевой версией JVM, которая несколько раньше последней - в противном случае некоторые пользователи будут вынуждены обновлять свою JVM для запуска вашего программного обеспечения, а некоторые из них выиграли у вас есть права администратора для этого.)
Если результат long
приведет к возврату вашего метода Java в диапазоне [-9,007,199,254,740,992 до 9,007,199,254,740,992], вам не нужно вообще ничего делать в своем коде. Вы можете преобразовать результат обратно в Matlab int64
без потери точности. Все целые числа в этом диапазоне могут быть представлены в виде double
чисел без потери точности, потому что значение может быть сохранено в 53-битных значащих двоичных разрядах, предлагаемых 64-битным представлением double
.
Более подробную информацию вы можете найти в главе 8 (Арифметика с плавающей запятой) моей книги Качество кода: перспектива с открытым исходным кодом или любой другой учебник покрывая арифметику с плавающей запятой.
Следующая программа демонстрирует точность представления double
для 100 миллионов целых чисел в конце точно отображаемого диапазона.
#include <stdio.h>
int
main(int argc, char *argv[])
{
int i;
volatile long long n1, n2;
volatile long long p1, p2;
volatile double d;
/* Include one number outside the range, to show that the test works. */
n1 = -9007199254740993ll;
p1 = 9007199254740993ll;
for (i = 0; i < 100000000; i++) {
d = p1;
p2 = d;
if (p1 != p2)
printf("%lld != %lld\n", p1, p2);
d = n1;
n2 = d;
if (n1 != n2)
printf("%lld != %lld\n", n1, n2);
p1--;
n1++;
}
return 0;
}
volatile
s только помогают с многопоточным кодом?