获得从R到Java的长值

时间:2016-03-14 09:32:02

标签: java r jri

我正在使用JRI并希望将R中的数值作为原始长度输入java。 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>

有人可以帮助我获得正确的长值吗?

更新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)返回INTSXP,然后调用本机方法rniGetIntArray(long)。我认为,这最后一次通话会导致溢出。

1 个答案:

答案 0 :(得分:2)

您的测试不会测试任何接近您所描述的内容,long根本不参与。您只需将NA_integer_从R传递给Java,因为添加会溢出32位整数并在R中发出警告。您可以使用isNA()方法检查它。如果要避免算术溢出,请使用R。

中的数字类型