Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

matlab - How to get int64 from a Java method returning a long?

According to Matlab documentation, when a Java method returns a long, it is converted to a double before being assigned in Matlab.

Precision has been lost. I am interested in the lower digits of the long returned by the Java method. A double cannot represent them, but Matlab's int64 can. (This is clear by considering that both types have 64 bits, and a double uses some of them to represent the exponent.)

If I had control of the Java code, I could return an array with one element, containing the long — in this case Matlab keeps them as int64s, but in my case I'm calling a library function.

Currently, the best way I can see is writing a wrapper in Java that will call the method and return the answer in an array. But there are portability issues with this approach. Is there a better way?

like image 881
Evgeni Sergeev Avatar asked May 01 '13 06:05

Evgeni Sergeev


2 Answers

If the long results that your Java method returns are in the range [-9,007,199,254,740,992 to 9,007,199,254,740,992], then you don't need to do anything at all in your code. You can convert the result back to Matlab's int64, without any loss of precision. All integers in that range can be represented as double numbers without a loss in precision, because the value can be stored in the 53-bit significant binary digits offered by the 64-bit representation of double values.

You can find more details in Chapter 8 (Floating-Point Arithmetic) of my book Code Quality: The Open Source Perspective or any other textbook covering floating point arithmetic.

The following program demonstrates the accuracy of the double representation for the 100 million integers at the end of the exactly representable range.

#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; } 
like image 67
Diomidis Spinellis Avatar answered Sep 20 '22 10:09

Diomidis Spinellis


It's been essentially answered in the comments, but just for completeness, the best way to receive a Java long into Matlab as int64 unharmed does seem to be writing a small Java wrapper which calls whatever method you have and returns the response in a long[].

(If the code is to be distributed, consider compiling that Java class with a target JVM version that is somewhat earlier than the latest — otherwise some users will be forced to upgrade their JVM to run your software, and some of those won't have admin rights to do that.)

like image 37
Evgeni Sergeev Avatar answered Sep 22 '22 10:09

Evgeni Sergeev