获取从 R 到 java 的长值
Getting a long value from R to java
我正在使用 JRI 并希望从 R 中获取一个数值作为原始 long 到 java。 class org.rosuda.REngine.REXP 只提供asDouble() 和asInteger() 方法。两者都没有按预期工作。好像是溢出问题
有两个单元测试:第一个使用方法 asDouble(),第二个使用 asString()(并且可以扩展为使用 BigInteger.longValue())。
@Test
public final void testWithDouble() throws Exception {
REngine engine;
engine = REngine.engineForClass("org.rosuda.REngine.JRI.JRIEngine");
engine.parseAndEval("rm(list=ls(all=TRUE))");
engine.assign("a", new int[] { 100000 });
engine.parseAndEval("b <- a * a");
REXP exp = engine.parseAndEval("b", null, true);
double b = exp.asDouble();
System.out.println(b); // prints -2.147483648E9
Assert.assertEquals(1e10, b, 1.0);
}
@Test
public final void testWithBigInteger() throws Exception {
REngine engine;
engine = REngine.engineForClass("org.rosuda.REngine.JRI.JRIEngine");
engine.parseAndEval("rm(list=ls(all=TRUE))");
engine.assign("a", new int[] { 100000 });
engine.parseAndEval("b <- a * a");
REXP exp = engine.parseAndEval("options(scipen=99); toString(b)", null, true);
String b = exp.asString();
System.out.println(b); // prints "NA"
Assert.assertEquals("10000000000", b);
// Now, this can be used to create a BigInteger and then the method longValue() helps.
}
我的 pom.xml 中有以下部分:
<dependency>
<groupId>com.github.lucarosellini.rJava</groupId>
<artifactId>JRIEngine</artifactId>
<version>0.9-7</version>
</dependency>
谁能帮我得到正确的 long 值?
更新 2016-03-17
我在 pom.xml 中添加了新版本的 REngine。对于工件 JRIEngine 和 JRI,我没有找到比 0.9-7 更新的版本。
<dependency>
<groupId>org.rosuda.REngine</groupId>
<artifactId>REngine</artifactId>
<version>2.1.0</version>
</dependency>
问题都是一样的。
testWithDouble()
的调试显示调用了原生方法rniExpType(long)
returnsINTSXP
,然后调用了原生方法rniGetIntArray(long)
。我认为,最后一次调用会导致溢出。
您的测试没有测试任何接近您所描述的内容,long
根本不涉及。您只是将 NA_integer_
从 R 传递给 Java,因为加法会溢出 32 位整数并在 R 中发出警告。您可以使用 isNA()
方法检查它。如果要避免算术溢出,请使用R中的数字类型。
我正在使用 JRI 并希望从 R 中获取一个数值作为原始 long 到 java。 class org.rosuda.REngine.REXP 只提供asDouble() 和asInteger() 方法。两者都没有按预期工作。好像是溢出问题
有两个单元测试:第一个使用方法 asDouble(),第二个使用 asString()(并且可以扩展为使用 BigInteger.longValue())。
@Test
public final void testWithDouble() throws Exception {
REngine engine;
engine = REngine.engineForClass("org.rosuda.REngine.JRI.JRIEngine");
engine.parseAndEval("rm(list=ls(all=TRUE))");
engine.assign("a", new int[] { 100000 });
engine.parseAndEval("b <- a * a");
REXP exp = engine.parseAndEval("b", null, true);
double b = exp.asDouble();
System.out.println(b); // prints -2.147483648E9
Assert.assertEquals(1e10, b, 1.0);
}
@Test
public final void testWithBigInteger() throws Exception {
REngine engine;
engine = REngine.engineForClass("org.rosuda.REngine.JRI.JRIEngine");
engine.parseAndEval("rm(list=ls(all=TRUE))");
engine.assign("a", new int[] { 100000 });
engine.parseAndEval("b <- a * a");
REXP exp = engine.parseAndEval("options(scipen=99); toString(b)", null, true);
String b = exp.asString();
System.out.println(b); // prints "NA"
Assert.assertEquals("10000000000", b);
// Now, this can be used to create a BigInteger and then the method longValue() helps.
}
我的 pom.xml 中有以下部分:
<dependency>
<groupId>com.github.lucarosellini.rJava</groupId>
<artifactId>JRIEngine</artifactId>
<version>0.9-7</version>
</dependency>
谁能帮我得到正确的 long 值?
更新 2016-03-17
我在 pom.xml 中添加了新版本的 REngine。对于工件 JRIEngine 和 JRI,我没有找到比 0.9-7 更新的版本。
<dependency>
<groupId>org.rosuda.REngine</groupId>
<artifactId>REngine</artifactId>
<version>2.1.0</version>
</dependency>
问题都是一样的。
testWithDouble()
的调试显示调用了原生方法rniExpType(long)
returnsINTSXP
,然后调用了原生方法rniGetIntArray(long)
。我认为,最后一次调用会导致溢出。
您的测试没有测试任何接近您所描述的内容,long
根本不涉及。您只是将 NA_integer_
从 R 传递给 Java,因为加法会溢出 32 位整数并在 R 中发出警告。您可以使用 isNA()
方法检查它。如果要避免算术溢出,请使用R中的数字类型。