All Downloads are FREE. Search and download functionalities are using the official Maven repository.

shz.core.NumberHelp Maven / Gradle / Ivy

There is a newer version: 2024.0.2
Show newest version
package shz.core;

import shz.core.function.CharConsumer;
import shz.core.function.CharSequenceVisitor;
import shz.core.function.CharSupplier;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.DoubleAdder;
import java.util.concurrent.atomic.LongAdder;

public final class NumberHelp {
    private NumberHelp() {
        throw new IllegalStateException();
    }

    public static Byte getByte(Object obj) {
        if (obj == null) return null;
        if (obj instanceof Byte) return (Byte) obj;
        if (obj instanceof Number) return ((Number) obj).byteValue();
        if (obj instanceof CharSequence) try {
            return Byte.parseByte(obj.toString());
        } catch (NumberFormatException e) {
            return null;
        }
        if (obj instanceof Boolean) return (byte) ((boolean) obj ? 1 : 0);
        if (obj instanceof Character) {
            int delta = (char) obj - '0';
            return delta < 0 || delta > 9 ? null : (byte) delta;
        }
        return null;
    }

    public static Short getShort(Object obj) {
        if (obj == null) return null;
        if (obj instanceof Short) return (Short) obj;
        if (obj instanceof Number) return ((Number) obj).shortValue();
        if (obj instanceof CharSequence) try {
            return Short.parseShort(obj.toString());
        } catch (NumberFormatException e) {
            return null;
        }
        if (obj instanceof Boolean) return (short) ((boolean) obj ? 1 : 0);
        if (obj instanceof Character) {
            int delta = (char) obj - '0';
            return delta < 0 || delta > 9 ? null : (short) delta;
        }
        return null;
    }

    public static Integer getInteger(Object obj) {
        if (obj == null) return null;
        if (obj instanceof Integer) return (Integer) obj;
        if (obj instanceof Number) return ((Number) obj).intValue();
        if (obj instanceof CharSequence) try {
            return Integer.parseInt(obj.toString());
        } catch (NumberFormatException e) {
            return null;
        }
        if (obj instanceof Boolean) return (boolean) obj ? 1 : 0;
        if (obj instanceof Character) {
            int delta = (char) obj - '0';
            return delta < 0 || delta > 9 ? null : delta;
        }
        return null;
    }

    public static Long getLong(Object obj) {
        if (obj == null) return null;
        if (obj instanceof Long) return (Long) obj;
        if (obj instanceof Number) return ((Number) obj).longValue();
        if (obj instanceof CharSequence) try {
            return Long.parseLong(obj.toString());
        } catch (NumberFormatException e) {
            return null;
        }
        if (obj instanceof Boolean) return (boolean) obj ? 1L : 0L;
        if (obj instanceof Character) {
            int delta = (char) obj - '0';
            return delta < 0 || delta > 9 ? null : (long) delta;
        }
        return null;
    }

    public static Float getFloat(Object obj) {
        if (obj == null) return null;
        if (obj instanceof Float) return (Float) obj;
        if (obj instanceof Number) return ((Number) obj).floatValue();
        if (obj instanceof CharSequence) try {
            return Float.parseFloat(obj.toString());
        } catch (NumberFormatException e) {
            return null;
        }
        if (obj instanceof Boolean) return (boolean) obj ? 1f : 0f;
        if (obj instanceof Character) {
            int delta = (char) obj - '0';
            return delta < 0 || delta > 9 ? null : (float) delta;
        }
        return null;
    }

    public static Double getDouble(Object obj) {
        if (obj == null) return null;
        if (obj instanceof Double) return (Double) obj;
        if (obj instanceof Number) return ((Number) obj).doubleValue();
        if (obj instanceof CharSequence) try {
            return Double.parseDouble(obj.toString());
        } catch (NumberFormatException e) {
            return null;
        }
        if (obj instanceof Boolean) return (boolean) obj ? 1D : 0D;
        if (obj instanceof Character) {
            int delta = (char) obj - '0';
            return delta < 0 || delta > 9 ? null : (double) delta;
        }
        return null;
    }

    public static BigInteger getBigInteger(Object obj) {
        if (obj == null) return null;
        if (obj instanceof BigInteger) return (BigInteger) obj;
        if (obj instanceof Number) return BigInteger.valueOf(((Number) obj).longValue());
        if (obj instanceof CharSequence) try {
            return new BigInteger(obj.toString());
        } catch (NumberFormatException e) {
            return null;
        }
        if (obj instanceof Boolean) return (boolean) obj ? BigInteger.ONE : BigInteger.ZERO;
        if (obj instanceof Character) {
            int delta = (char) obj - '0';
            if (delta < 0 || delta > 9) return null;
            return delta == 0 ? BigInteger.ZERO : delta == 1 ? BigInteger.ONE : BigInteger.valueOf(delta);
        }
        return null;
    }

    public static BigDecimal getBigDecimal(Object obj) {
        if (obj == null) return null;
        if (obj instanceof BigDecimal) return (BigDecimal) obj;
        if (obj instanceof Number || obj instanceof CharSequence) try {
            return new BigDecimal(obj.toString());
        } catch (NumberFormatException e) {
            return null;
        }
        if (obj instanceof Boolean) return (boolean) obj ? BigDecimal.ONE : BigDecimal.ZERO;
        if (obj instanceof Character) {
            int delta = (char) obj - '0';
            if (delta < 0 || delta > 9) return null;
            return delta == 0 ? BigDecimal.ZERO : delta == 1 ? BigDecimal.ONE : BigDecimal.valueOf(delta);
        }
        return null;
    }

    public static AtomicInteger getAtomicInteger(Object obj) {
        if (obj == null) return null;
        if (obj instanceof AtomicInteger) return (AtomicInteger) obj;
        if (obj instanceof Number) return new AtomicInteger(((Number) obj).intValue());
        if (obj instanceof CharSequence) try {
            return new AtomicInteger(Integer.parseInt(obj.toString()));
        } catch (NumberFormatException e) {
            return null;
        }
        if (obj instanceof Boolean) return (boolean) obj ? new AtomicInteger(1) : new AtomicInteger();
        if (obj instanceof Character) {
            int delta = (char) obj - '0';
            return delta < 0 || delta > 9 ? null : new AtomicInteger(delta);
        }
        return null;
    }

    public static AtomicLong getAtomicLong(Object obj) {
        if (obj == null) return null;
        if (obj instanceof AtomicLong) return (AtomicLong) obj;
        if (obj instanceof Number) return new AtomicLong(((Number) obj).longValue());
        if (obj instanceof CharSequence) try {
            return new AtomicLong(Long.parseLong(obj.toString()));
        } catch (NumberFormatException e) {
            return null;
        }
        if (obj instanceof Boolean) return (boolean) obj ? new AtomicLong(1L) : new AtomicLong();
        if (obj instanceof Character) {
            int delta = (char) obj - '0';
            return delta < 0 || delta > 9 ? null : new AtomicLong(delta);
        }
        return null;
    }

    public static LongAdder getLongAdder(Object obj) {
        if (obj == null) return null;
        if (obj instanceof LongAdder) return (LongAdder) obj;
        if (obj instanceof Number) {
            LongAdder adder = new LongAdder();
            adder.add(((Number) obj).longValue());
            return adder;
        }
        if (obj instanceof CharSequence) try {
            long value = Long.parseLong(obj.toString());
            LongAdder adder = new LongAdder();
            adder.add(value);
            return adder;
        } catch (NumberFormatException e) {
            return null;
        }
        if (obj instanceof Boolean) {
            LongAdder adder = new LongAdder();
            if ((boolean) obj) adder.add(1L);
            return adder;
        }
        if (obj instanceof Character) {
            int delta = (char) obj - '0';
            if (delta < 0 || delta > 9) return null;
            LongAdder adder = new LongAdder();
            adder.add(delta);
            return adder;
        }
        return null;
    }

    public static DoubleAdder getDoubleAdder(Object obj) {
        if (obj == null) return null;
        if (obj instanceof DoubleAdder) return (DoubleAdder) obj;
        if (obj instanceof Number) {
            DoubleAdder adder = new DoubleAdder();
            adder.add(((Number) obj).doubleValue());
            return adder;
        }
        if (obj instanceof CharSequence) try {
            double value = Double.parseDouble(obj.toString());
            DoubleAdder adder = new DoubleAdder();
            adder.add(value);
            return adder;
        } catch (NumberFormatException e) {
            return null;
        }
        if (obj instanceof Boolean) {
            DoubleAdder adder = new DoubleAdder();
            if ((boolean) obj) adder.add(1D);
            return adder;
        }
        if (obj instanceof Character) {
            int delta = (char) obj - '0';
            if (delta < 0 || delta > 9) return null;
            DoubleAdder adder = new DoubleAdder();
            adder.add(delta);
            return adder;
        }
        return null;
    }

    public static String setScale(double val, int scale) {
        return new BigDecimal(Double.toString(val)).setScale(scale, RoundingMode.HALF_UP).toString();
    }

    /**
     * 移除尾部的0
     */
    public static String stripTail0(String s) {
        int len;
        if ((len = NullHelp.length(s)) == 0) return s;
        while (s.charAt(len - 1) == '0') --len;
        if (s.charAt(len - 1) == '.') --len;
        if (len == s.length()) return s;
        char[] chars = new char[len];
        s.getChars(0, len, chars, 0);
        return new String(chars);
    }

    /**
     * 格式化科学计数法字符串
     */
    public static boolean scientific(CharSequenceVisitor visitor, CharConsumer action, String s, int idx) {
        int len;
        if (idx == 0 || (len = NullHelp.length(s)) == 0) return false;
        int dot = s.indexOf(".");
        if (idx > 0) {
            if (dot == -1) {
                visitor.accept(s, 0, len);
                for (int i = 0; i < idx; ++i) action.accept('0');
                return true;
            }

            int start = 0;
            int end = dot + 1 + idx;
            //去除首部的0
            while (s.charAt(start) == '0') ++start;
            if (start == dot) {
                ++start;
                int limit = Math.min(len, end);
                while (start < limit && s.charAt(start) == '0') ++start;
            }

            if (len <= end) {
                if (start < dot) {
                    visitor.accept(s, start, dot);
                    visitor.accept(s, dot + 1, len);
                } else if (start < len) visitor.accept(s, start, len);
                for (int i = 0; i < end - len; ++i) action.accept('0');
                return true;
            }

            if (start < dot) {
                visitor.accept(s, start, dot);
                visitor.accept(s, dot + 1, end);
            } else if (start < end) visitor.accept(s, start, end);
            else action.accept('0');
            action.accept('.');
            visitor.accept(s, end, len);
            return true;
        }

        idx = -idx;
        if (dot == -1) {
            if (idx < len) {
                visitor.accept(s, 0, len - idx);
                action.accept('.');
                visitor.accept(s, len - idx, len);
                return true;
            }
            action.accept('0');
            action.accept('.');
            for (int i = 2; i < idx - len + 2; ++i) action.accept('0');
            visitor.accept(s, 0, len);
            return true;
        }

        if (idx < dot) {
            visitor.accept(s, 0, dot - idx);
            action.accept('.');
            visitor.accept(s, dot - idx, dot);
            visitor.accept(s, dot + 1, len);
            return true;
        }

        action.accept('0');
        action.accept('.');
        for (int i = 2; i < idx - dot + 2; ++i) action.accept('0');
        visitor.accept(s, 0, dot);
        visitor.accept(s, dot + 1, len);
        return true;
    }

    public static boolean scientific(CharSequenceVisitor visitor, CharConsumer action, String s) {
        if (NullHelp.isBlank(s)) return false;
        String[] arr;
        if (s.indexOf('E') != -1) arr = s.split("E");
        else if (s.indexOf('e') != -1) arr = s.split("e");
        else return false;
        if (arr.length != 2) return false;
        if (!RegexHelp.P_DIGITAL.matcher(arr[0]).matches() || !RegexHelp.P_BYTE.matcher(arr[1]).matches()) return false;
        return scientific(visitor, action, arr[0], Integer.parseInt(arr[1]));
    }

    public static String scientific(String s, int idx) {
        if (idx == 0 || NullHelp.isEmpty(s)) return s;
        StringBuilder sb = new StringBuilder();
        return scientific(sb::append, sb::append, s, idx) ? sb.toString() : s;
    }

    public static String scientific(String s) {
        if (NullHelp.isBlank(s)) return s;
        StringBuilder sb = new StringBuilder();
        return scientific(sb::append, sb::append, s) ? sb.toString() : s;
    }

    private static final char[] DIGIT = {'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'};
    private static final char[] INDEX = {'拾', '佰', '仟', '万', '亿'};
    private static final char[] UNIT = {'元', '角', '分'};
    private static final char I = '整';

    /**
     * 转大写人民币
     * 会截取最多两位小数(不做进位处理),如需四舍五入需要提前处理数据
     */
    public static void toCapitalRmb(CharConsumer action, CharSupplier tail, Runnable cancelTail, double val) {
        String s = Double.toString(val);
        int end = s.length();
        int R = end;
        int dot = s.indexOf('.');
        if (dot != -1) {
            //移除尾部的0
            while (s.charAt(end - 1) == '0') --end;
            //获取整数的右边界
            if (s.charAt(end - 1) == '.') R = --end;
            else R = dot;
        }

        //处理整数部分
        toCapitalRmb0(s, 0, R, action, tail, cancelTail);
        if (tail.getAsChar() == DIGIT[0]) cancelTail.run();
        action.accept(UNIT[0]);

        if (R == end) {
            action.accept(I);
            return;
        }

        //小数加零
        action.accept(DIGIT[0]);
        //只取两位到分
        end = Math.min(dot + 3, end);
        for (int i = dot + 1; i < end; ++i)
            if (s.charAt(i) != '0') {
                action.accept(DIGIT[s.charAt(i) - '0']);
                action.accept(UNIT[i - dot]);
            }
    }

    private static void toCapitalRmb0(String s, int L, int R, CharConsumer action, CharSupplier tail, Runnable cancelTail) {
        if (R - L >= 9) {
            toCapitalRmb0(s, L, R - 8, action, tail, cancelTail);
            dealRmb0(INDEX[4], action, tail, cancelTail);
            toCapitalRmb0(s, R - 8, R, action, tail, cancelTail);
            return;
        }
        if (R - L >= 5) {
            toCapitalRmb0(s, L, R - 4, action, tail, cancelTail);
            dealRmb0(INDEX[3], action, tail, cancelTail);
            toCapitalRmb0(s, R - 4, R, action, tail, cancelTail);
            return;
        }
        boolean mark0 = tail.getAsChar() == DIGIT[0];
        char c;
        for (int i = L; i < R; ++i) {
            c = s.charAt(i);
            if (c == '0') {
                if (!mark0) {
                    action.accept(DIGIT[0]);
                    mark0 = true;
                }
            } else {
                if (R - 2 - i > 0) {
                    action.accept(DIGIT[c - '0']);
                    action.accept(INDEX[R - 2 - i]);
                } else if (R - 2 - i == 0) {
                    action.accept(DIGIT[c - '0']);
                    action.accept(INDEX[0]);
                } else action.accept(DIGIT[c - '0']);
                mark0 = false;
            }
        }
    }

    private static void dealRmb0(char c, CharConsumer action, CharSupplier tail, Runnable cancelTail) {
        if (tail.getAsChar() == DIGIT[0]) {
            cancelTail.run();
            appendRmbIndex0(c, action, tail);
            action.accept(DIGIT[0]);
        } else appendRmbIndex0(c, action, tail);
    }

    private static void appendRmbIndex0(char c, CharConsumer action, CharSupplier tail) {
        char prev = tail.getAsChar();
        int prevIdx = -1;
        int currentIdx = -1;
        for (int i = 0; i < INDEX.length; ++i) {
            if (prev == INDEX[i]) prevIdx = i;
            if (c == INDEX[i]) currentIdx = i;
        }
        if (prevIdx <= currentIdx) action.accept(c);
    }

    public static String toCapitalRmb(double val) {
        StringBuilder sb = new StringBuilder(20).append("人民币");
        toCapitalRmb(sb::append, () -> sb.charAt(sb.length() - 1), () -> sb.deleteCharAt(sb.length() - 1), val);
        return sb.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy