Question

I have a JNI application.

In the Java implementation, I have the following

float floatValue = 23.45f;
Object[] objArray = new Object[] { floatValue } ;

When I call a native method, passing over my object array, and in CPP I do the following:

JNIEXPORT void JNICALL Java_my_method(JNIEnv * env, jobject objInstance, jobjectArray objArray){
    jclass floatClass = env->FindClass("java/lang/Float"); 
    jmethodID floatMethod = env->GetMethodID(floatClass, "floatValue", "()F");
    jobject obj = env->GetObjectArrayElement(objArray, 0);
    jfloat val = env->CallFloatMethod(obj, floatMethod);
    printf("JNI received float value: %f\n",val);
}

It prints:

JNI received float value: 23.450001

Any ideas?

Was it helpful?

Solution 2

I can think of three different ways of looking at what a float represents.

  • You can say that a float is an exact value, which is the number that the 0's and 1's that make up the float represent in binary. A float is made up of a mantissa, an exponent and a sign bit, and you can do the mathematics to turn those 0's and 1's into an actual number. This is the most common way of looking at a float, and most people would consider it the most correct way.
  • You can think of a float as representing a range of values - basically all the numbers that closer to that float than to any other. This is useful when you've used a float for measuring something.
  • You can think of a float as representing the particular number within that range, which has the shortest decimal expansion. This idea is fraught with problems, but it has influenced the way Java works with floating point.

So consider the number x = 23.450000762939453125. This number happens to be represented exactly by a float, which I'll call f - that is, break f into its mantissa and exponent, do the calculation, and x will come out.

The next number below x that has can be represented exactly by a float is x - h = 23.4499988555908203125. And the next number above x that can be represented exactly by a float is x + h = 23.4500026702880859375. I've just used h to denote the gap between consecutive float numbers around this magnitude.

Now, if you have any number in the range x - h / 2 = 23.44999980926513671875 up to x + h / 2 = 23.45000171661376953125, then the closest float to your number will be f. So that is the range of numbers that are represented by f - and of course, x is right in the middle of this range.

You'll notice that 23.45 is in that range, and so is 23.450001. What that means is that if you take the Java float literal 23.45F, its value is in fact f. The same is true of the Java float literal 23.450001F. And that's why the expression (23.45F == 23.450001F) works out to be true.

Now, when we try to print this float number f, things start to get different between C++ and Java.

  • In C++, the default way of printing a float is to find the number that it represents exactly, and round it to six decimal places. So what you get is x rounded to six decimal places, which of course is 23.450001.
  • In Java, the default way of printing a float is to find the number within the represented range, with the shortest decimal expansion. In other words, Java will look for the number between x - h / 2 and x + h / 2 that it can write with the smallest number of decimal places. This number is 23.45.

So any C++ program will show f as 23.450001, unless you specifically instruct the program to show it differently. Any Java program will show f as 23.45, unless you specifically instruct the program to show it differently. But it's all the same float.

OTHER TIPS

23.45 == 23.450001 so there's no problem.

If you're surprised about that equivalence, it's true both in C++ and in Java regardless of JNI. It follows from the limited precision of the common underlying floating point type.

If someone is looking for a cosmetic solution, you can always change the output precision of printf() by changing:

printf("JNI received float value: %f\n",val);

to something like:

printf("JNI received float value: %f.4\n",val);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top