将浮点数从Java传递给JNI,额外小数

时间:2014-05-12 12:11:08

标签: java c++ java-native-interface

我有一个JNI应用程序。

在Java实现中,我有以下

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

当我调用本机方法,遍历我的对象数组时,在CPP中我执行以下操作:

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

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

23.45 == 23.450001所以没有问题。

如果你对这种等价感到惊讶,无论是在JNI还是在C ++和Java中都是如此。它遵循公共底层浮点类型的有限精度。

答案 1 :(得分:0)

如果有人正在寻找化妆品解决方案,您可以随时更改输出 printf()的精度通过改变:

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

类似于:

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

答案 2 :(得分:0)

我可以想出三种不同的方式来查看float所代表的内容。

  • 您可以说float是一个确切的值,即构成float的0和1代表二进制的数字。 float由尾数,指数和符号位组成,您可以使用数学将这些0和1转换为实际数字。这是查看float的最常见方式,大多数人会认为这是最正确的方式。
  • 您可以将float视为代表一系列值 - 基本上所有数字都接近float而不是任何其他数字。当您使用float进行测量时,这非常有用。
  • 您可以将float视为代表该范围内的特定数字,该数字具有最短的十进制扩展。这个想法充满了问题,但它影响了Java使用浮点的方式。

所以考虑一下x = 23.450000762939453125。这个数字恰好由float表示,我称之为 f - 也就是说,将 f 分解为尾数和指数,进行计算,x将会出来。

x下面的下一个数字x - h = 23.4499988555908203125可以用浮点数精确表示x。可以由浮点数精确表示的x + h = 23.4500026702880859375以上的下一个数字是h。我刚刚使用float来表示这个数量级附近的连续x - h / 2 = 23.44999980926513671875数字之间的差距。

现在,如果您的x + h / 2 = 23.45000171661376953125范围内的任何数字最多为float,那么与您的号码最接近的x将为 f 。这是由 f 表示的数字范围 - 当然,23.45正好在此范围的中间。

您会注意到23.450001在此范围内,float也是如此。这意味着如果您使用Java 23.45F文字float,其值实际上是 f 。 Java 23.450001F文字(23.45F == 23.450001F)也是如此。这就是表达式true成为float的原因。

现在,当我们尝试打印此float数字 f 时,C ++和Java之间的情况开始变得不同。

  • 在C ++中,打印x的默认方法是找到它所代表的数字,并将其四舍五入到小数点后六位。所以你得到的是23.450001四舍五入到小数点后六位,当然是float
  • 在Java中,打印x - h / 2的默认方式是查找所表示范围内的数字,并使用最短的十进制扩展。换句话说,Java将查找x + h / 223.45之间的数字,它可以用最小的小数位数写入。这个数字是23.450001

因此,除非您明确指示程序以不同方式显示,否则任何C ++程序都会将 f 显示为23.45。任何Java程序都会将 f 显示为float,除非您明确指示程序以不同方式显示它。但它完全相同{{1}}。