将float从Java传递到JNI,额外的小数 [英] Passing float from Java to JNI, extra decimals
问题描述
我有一个JNI应用程序。
I have a JNI application.
在Java实现中,我有以下
In the Java implementation, I have the following
float floatValue = 23.45f;
Object[] objArray = new Object[] { floatValue } ;
当我调用一个本地方法,传递我的对象数组,并在CPP中,我做以下:
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);
}
打印:
JNI received float value: 23.450001
/ p>
Any ideas?
推荐答案
我可以想出三种不同的方式来查看 float
I can think of three different ways of looking at what a float
represents.
- 您可以说
float
是一个精确的值,构成float
的0和1的数字以二进制表示。float
由尾数,指数和符号位组成,你可以通过数学将这些0和1转换为实数。这是查看float
最常见的方式,大多数人会认为它是最正确的方式。 - 一个
float
表示一个范围的值 - 基本上所有更接近float
的数字比任何其他。当你使用float
来测量某些东西时,这很有用。 - 你可以想到
float
表示该范围内具有最小十进制扩展的特定数字。这个想法充满了问题,但它影响了Java与浮点的工作方式。
- You can say that a
float
is an exact value, which is the number that the 0's and 1's that make up thefloat
represent in binary. Afloat
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 afloat
, 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 thatfloat
than to any other. This is useful when you've used afloat
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.
因此,请考虑 x = 23.450000762939453125
。这个数字恰好由 float
表示,我将称为 f - 也就是break f 到它的尾数和指数,进行计算, x
将会出来。
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.
c $ c> x ,可以通过一个float来精确表示 x - h = 23.4499988555908203125
。并且可以通过float精确表示的 x
下面的数字是 x + h = 23.4500026702880859375
。我刚刚使用 h
来表示连续 float
数字之间的差距。
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.
现在,如果您在 x - h / 2 = 23.44999980926513671875
范围内有任何数字,最多 x + h / 2 = 23.45000171661376953125
,那么最接近您的号码的 float
将是 f 。所以这是由 f 表示的数字范围 - 当然, x
正好在这个范围的中间。
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.
您会注意到 23.45
在该范围内,因此 23.450001
。这意味着如果你使用Java float
literal 23.45F
,它的值实际上是f 。 Java float
literal 23.450001F
也是如此。这就是为什么表达式(23.45F == 23.450001F)
的原理是 true
。
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
.
现在,当我们尝试打印这个 float
number f 时,事情开始得到不同的C ++和Java。
Now, when we try to print this float
number f, things start to get different between C++ and Java.
- 在C ++中,打印
float
的默认方式是查找数字它表示精确,并将其舍入到六个小数位。所以你得到的是x
四舍五入到小数点后六位,当然是23.450001
。 - 在Java中,打印
float
的默认方式是使用最小的十进制扩展找出所表示范围内的数字。换句话说,Java将寻找x - h / 2
和x + h / 2
之间的数字可以用最小的小数位数写入。这个数字是23.45
。
- 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 isx
rounded to six decimal places, which of course is23.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 betweenx - h / 2
andx + h / 2
that it can write with the smallest number of decimal places. This number is23.45
.
f 为 23.450001
,除非您特别指示程序以不同方式显示。任何Java程序将显示 f 为 23.45
,除非您特别指示程序以不同方式显示。但它都是一样的 float
。
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
.
这篇关于将float从Java传递到JNI,额外的小数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!