本文为您介绍如何通过Java UDF实现不同类型数值相除获取余数。

取余函数UDF说明

Integer UDFPMod(INTEGER a, INTEGER b)
Long UDFPMod(Long a, Long b)
Double UDFPMod(Double a, Double b)           
  • 函数功能:返回a除以b的余数。
  • 参数说明:
    • a:被除数,支持INTEGER、Long以及Double类型。
    • b:除数,支持INTEGER、Long以及Double类型。

UDF使用示例

  • 注册函数
    UDFPMod.java测试通过后,将其注册为函数使用。
    说明 一个UDF从发布到服务端供生产使用,需要经过打包、上传、注册这三个步骤。您可以使用一键发布功能一次性完成这些步骤(Studio会依次执行mvn clean package、上传Jar和注册UDF这三个步骤)。详情请参见打包、上传和注册
  • 使用示例
    成功注册UDF后,执行以下命令:
    • 示例一
      select pmodTest(-9L,-4L) from dual;
      运行结果如下。
      +-----+
      | _c0 |
      +-----+
      | -1  |
      +-----+
    • 示例二
      select pmodTest(9.0,-4.0) from dual;
      运行结果如下。
      +-----+
      | _c0 |
      +-----+
      | -3.0 |
      +-----+
    • 示例三
      select pmodTest(9,4) from dual;
      运行结果如下。
      +-----+
      | _c0 |
      +-----+
      | 1   |
      +-----+

UDF代码示例

package com.aliyun.odps.examples.udf// package名称,可以根据您的情况定义。
import com.aliyun.odps.udf.UDF;
public class UDFPMod extends UDF {
    // 使用Long类型的数据。
    public String evaluate(Long  a,  Long  b)  {
        if  ((a  == null) || (b == null) || b==0L)  {
            return  null;
        }
        Long d=((a % b) + b) % b;
        return d.toString();
    }
    // 使用Double类型的数据。
    public String evaluate(Double a, Double b)  {
        if  ((a == null) || (b == null) || b==0.0)  {
            return  null;
        }
        Double d=((a % b) + b) % b;
        return d.toString() ;
    }
    // 使用Integer类型的数据。
    public String evaluate(Integer a, Integer b)  {
        if  ((a == null) || (b == null) || b==0)  {
            return  null;
        }
        Integer d=((a % b) + b) % b;
        return d.toString();
    }
}
说明 示例中为返回值类型做了toString处理,对测试结果无影响。

UDF单元测试

package com.aliyun.odps.examples.udf// package名称,可以根据您的情况定义。
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class TestUDFPMod {
    private UDFPMod udf = new UDFPMod();
    @Test
    public void test_null(){
        assertEquals(null, udf.evaluate(null, 1L));
        assertEquals(null, udf.evaluate(1L, null));
        assertEquals(null, udf.evaluate((Long)null, null));

        assertEquals(null, udf.evaluate(null, 1.0));
        assertEquals(null, udf.evaluate(1.0, null));
        assertEquals(null, udf.evaluate((Double)null, null));
    }
    @Test
    public void test_正常情况(){
        assertEquals(1L, udf.evaluate(9L, 4L));
        assertEquals(3L, udf.evaluate(-9L, 4L));
        assertEquals(-1L, udf.evaluate(-9L, -4L));
        assertEquals(-3L, udf.evaluate(9L, -4L));
        // 原来抛异常,现返回null。
        assertEquals(null, udf.evaluate(9L, 0L));

        assertEquals(1.0, udf.evaluate(9.0, 4.0));
        assertEquals(3.0, udf.evaluate(-9.0, 4.0));
        assertEquals(-1.0, udf.evaluate(-9.0, -4.0));
        assertEquals(-3.0, udf.evaluate(9.0, -4.0));
        // 原来返回Nan,现返回null。
        assertEquals(null, udf.evaluate(9.0, 0.0));
    }
}