unitsofmeasurement / indriya

JSR 385 - Reference Implementation
Other
115 stars 40 forks source link

quickly detects that BigDecimal is integer #388

Closed fengyizhu closed 1 year ago

fengyizhu commented 1 year ago
package com;

import tech.units.indriya.function.DefaultNumberSystem;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.concurrent.atomic.AtomicInteger;

package com.ke.nervecenter.type.pojos;

import tech.units.indriya.function.DefaultNumberSystem;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.concurrent.atomic.AtomicInteger;

public class TryCatchTest {

    public static void main(String[] args) {

        BigDecimal bigDecimal = new BigDecimal("3.1415926");
        DefaultNumberSystem defaultNumberSystem = new DefaultNumberSystem();

        long start = System.currentTimeMillis();
        for (int i=0;i<100000;i++){
            Number a = defaultNumberSystem.narrow(bigDecimal);
        }
        long end = System.currentTimeMillis() - start;
        System.out.println("default narrow time:" + end + " ms");

        start = System.currentTimeMillis();
        for (int i=0;i<100000;i++){
            Number a = quicklyNarrow(bigDecimal);
        }
        end = System.currentTimeMillis() - start;
        System.out.println("quickly narrow time:" + end + " ms");
    }
    private static Number quicklyNarrow(Number number){
        if(number instanceof Integer || number instanceof AtomicInteger ||
                number instanceof Short || number instanceof Byte) {
            return number;
        }
        if(number instanceof BigDecimal) {

            final BigDecimal decimal = ((BigDecimal) number);

            if( decimal.scale() <= 0){
                try {
                    BigInteger integer = decimal.toBigIntegerExact();
                    return quicklyNarrow(integer);
                } catch (ArithmeticException e) {
                    return number; // cannot narrow to integer
                }
            }
        }
        return number;
    }
}

console

default narrow time:107 ms
quickly narrow time:1 ms

This change is Reviewable

andi-huber commented 1 year ago

Certainly an option, thanks for that. We might be even able to avoid the try catch clause entirely. There are some interesting answers to the question on how to check whether a BigDecimal represents an integer: https://stackoverflow.com/questions/1078953/check-if-bigdecimal-is-an-integer-in-java

That said, I see no issue with your solution.