This topic describes how to use Java UDFs to obtain the remainders after values of different types are divided.

UDFs used to obtain remainders

Integer UDFPMod(INTEGER a, INTEGER b)
Long UDFPMod(Long a, Long b)
Double UDFPMod(Double a, Double b)           
  • Description: used to return the remainder by dividing a by b.
  • Parameters:
    • a: the dividend, which can be of the INTEGER, LONG, or DOUBLE type
    • b: the divisor, which can be of the INTEGER, LONG, or DOUBLE type

UDF example

  • Function registration
    After UDFPMod.java passes the test, register it as a function.
    Note To publish a UDF to a server for production use, the UDF needs to go through packaging, uploading, and registration. You can use the one-click publish function to complete these steps. MaxCompute Studio allows you to run the mvn clean package command, upload a JAR package, and register the UDF in sequence. For more information, see Package、Upload and Register.
  • Examples
    After the UDF is registered, execute one of the following statements:
    • Example 1
      select pmodTest(-9L,-4L) from dual;
      The result is as follows:
      +-----+
      | _c0 |
      +-----+
      | -1  |
      +-----+
    • Example 2
      select pmodTest(9.0,-4.0) from dual;
      The result is as follows:
      +-----+
      | _c0 |
      +-----+
      | -3.0 |
      +-----+
    • Example 3
      select pmodTest(9,4) from dual;
      The result is as follows:
      +-----+
      | _c0 |
      +-----+
      | 1   |
      +-----+

UDF code example

package com.aliyun.odps.examples.udf// The package name, which can be defined as needed.
import com.aliyun.odps.udf.UDF;
public class UDFPMod extends UDF {
    // Use data of the LONG type.
    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();
    }
    // Use data of the DOUBLE type.
    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() ;
    }
    // Use data of the INTEGER type.
    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();
    }
}
Note In this example, toString is performed on the type of the return value, but the test result is not affected.

UDF unit testing

package com.aliyun.odps.examples.udf// The package name, which can be defined as needed.
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_Normal cases(){
        assertEquals(1L, udf.evaluate(9L, 4L));
        assertEquals(3L, udf.evaluate(-9L, 4L));
        assertEquals(-1L, udf.evaluate(-9L, -4L));
        assertEquals(-3L, udf.evaluate(9L, -4L));
        // An error is returned if the code is not added. null is returned if the code is added.
        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 is returned if the code is not added. null is returned if the code is added.
        assertEquals(null, udf.evaluate(9.0, 0.0));
    }
}