BigDecimal类中的String参数类型的构造器(Java)
2021/9/27 11:10:54
本文主要是介绍BigDecimal类中的String参数类型的构造器(Java),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
JDK版本: JDK 8
构造方法
调用传入String类型的参数的构造器
public BigDecimal(String val) { this(val.toCharArray(), 0, val.length()); }
最终调用的是下面这个方法
/** * @param in String类对象各单个字符组成的char数组 * @param offset 初始为0 * @param len String对象的长度 * @param mc 这里传入的是MaxContext.UNLIMITED, 不限制有效位数, 采用四舍五入 */ public BigDecimal(char[] in, int offset, int len, MathContext mc)
查看构造器源码
public BigDecimal(char[] in, int offset, int len, MathContext mc) { // protect against huge length. if (offset + len > in.length || offset < 0) throw new NumberFormatException("Bad offset or len arguments for char[] input."); // This is the primary string to BigDecimal constructor; all // incoming strings end up here; it uses explicit (inline) // parsing for speed and generates at most one intermediate // (temporary) object (a char[] array) for non-compact case. // Use locals for all fields values until completion int prec = 0; // 有效数字位数 int scl = 0; // 小数点后有几位数 long rs = 0; // the compact value in long BigInteger rb = null; // the inflated value in BigInteger // use array bounds checking to handle too-long, len == 0, // bad offset, etc. try { // handle the sign boolean isneg = false; // assume positive if (in[offset] == '-') { isneg = true; // leading minus means negative offset++; len--; } else if (in[offset] == '+') { // leading + allowed offset++; len--; } // should now be at numeric part of the significand boolean dot = false; // true when there is a '.' long exp = 0; // exponent char c; // current character boolean isCompact = (len <= MAX_COMPACT_DIGITS); // integer significand array & idx is the index to it. The array // is ONLY used when we can't use a compact representation. int idx = 0; if (isCompact) { // First compact case, we need not to preserve the character // and we can just compute the value in place. for (; len > 0; offset++, len--) { c = in[offset]; if ((c == '0')) { // have zero if (prec == 0) prec = 1; else if (rs != 0) { rs *= 10; ++prec; } // else digit is a redundant leading zero if (dot) ++scl; } else if ((c >= '1' && c <= '9')) { // have digit int digit = c - '0'; if (prec != 1 || rs != 0) ++prec; // prec unchanged if preceded by 0s rs = rs * 10 + digit; if (dot) ++scl; } else if (c == '.') { // have dot // have dot if (dot) // two dots throw new NumberFormatException(); dot = true; } else if (Character.isDigit(c)) { // slow path int digit = Character.digit(c, 10); if (digit == 0) { if (prec == 0) prec = 1; else if (rs != 0) { rs *= 10; ++prec; } // else digit is a redundant leading zero } else { if (prec != 1 || rs != 0) ++prec; // prec unchanged if preceded by 0s rs = rs * 10 + digit; } if (dot) ++scl; } else if ((c == 'e') || (c == 'E')) { exp = parseExp(in, offset, len); // Next test is required for backwards compatibility if ((int) exp != exp) // overflow throw new NumberFormatException(); break; // [saves a test] } else { throw new NumberFormatException(); } } if (prec == 0) // no digits found throw new NumberFormatException(); // Adjust scale if exp is not zero. if (exp != 0) { // had significant exponent scl = adjustScale(scl, exp); } rs = isneg ? -rs : rs; int mcp = mc.precision; int drop = prec - mcp; // prec has range [1, MAX_INT], mcp has range [0, MAX_INT]; // therefore, this subtract cannot overflow if (mcp > 0 && drop > 0) { // do rounding while (drop > 0) { scl = checkScaleNonZero((long) scl - drop); rs = divideAndRound(rs, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode); prec = longDigitLength(rs); drop = prec - mcp; } } } else { char coeff[] = new char[len]; for (; len > 0; offset++, len--) { c = in[offset]; // have digit if ((c >= '0' && c <= '9') || Character.isDigit(c)) { // First compact case, we need not to preserve the character // and we can just compute the value in place. if (c == '0' || Character.digit(c, 10) == 0) { if (prec == 0) { coeff[idx] = c; prec = 1; } else if (idx != 0) { coeff[idx++] = c; ++prec; } // else c must be a redundant leading zero } else { if (prec != 1 || idx != 0) ++prec; // prec unchanged if preceded by 0s coeff[idx++] = c; } if (dot) ++scl; continue; } // have dot if (c == '.') { // have dot if (dot) // two dots throw new NumberFormatException(); dot = true; continue; } // exponent expected if ((c != 'e') && (c != 'E')) throw new NumberFormatException(); exp = parseExp(in, offset, len); // Next test is required for backwards compatibility if ((int) exp != exp) // overflow throw new NumberFormatException(); break; // [saves a test] } // here when no characters left if (prec == 0) // no digits found throw new NumberFormatException(); // Adjust scale if exp is not zero. if (exp != 0) { // had significant exponent scl = adjustScale(scl, exp); } // Remove leading zeros from precision (digits count) rb = new BigInteger(coeff, isneg ? -1 : 1, prec); rs = compactValFor(rb); int mcp = mc.precision; if (mcp > 0 && (prec > mcp)) { if (rs == INFLATED) { int drop = prec - mcp; while (drop > 0) { scl = checkScaleNonZero((long) scl - drop); rb = divideAndRoundByTenPow(rb, drop, mc.roundingMode.oldMode); rs = compactValFor(rb); if (rs != INFLATED) { prec = longDigitLength(rs); break; } prec = bigDigitLength(rb); drop = prec - mcp; } } if (rs != INFLATED) { int drop = prec - mcp; while (drop > 0) { scl = checkScaleNonZero((long) scl - drop); rs = divideAndRound(rs, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode); prec = longDigitLength(rs); drop = prec - mcp; } rb = null; } } } } catch (ArrayIndexOutOfBoundsException e) { throw new NumberFormatException(); } catch (NegativeArraySizeException e) { throw new NumberFormatException(); } this.scale = scl; this.precision = prec; this.intCompact = rs; this.intVal = rb; }
构造方法中的Character.isDigit(char c)
从源码中截取一部分代码,我们来看看Character.isDigit(char c)
这个方法
查看代码
for (; len > 0; offset++, len--) { c = in[offset]; if ((c == '0')) { // have zero if (prec == 0) prec = 1; else if (rs != 0) { rs *= 10; ++prec; } // else digit is a redundant leading zero if (dot) ++scl; } else if ((c >= '1' && c <= '9')) { // have digit int digit = c - '0'; if (prec != 1 || rs != 0) ++prec; // prec unchanged if preceded by 0s rs = rs * 10 + digit; if (dot) ++scl; } else if (c == '.'){ // 略 } else if (Character.isDigit(c)) { // slow path int digit = Character.digit(c, 10); if (digit == 0) { if (prec == 0) prec = 1; else if (rs != 0) { rs *= 10; ++prec; } // else digit is a redundant leading zero } else { if (prec != 1 || rs != 0) ++prec; // prec unchanged if preceded by 0s rs = rs * 10 + digit; } if (dot) ++scl; }
当时在看这段代码时,不明白为什么在已经判断了字符是否为0~9
,还要在后面调用Character.isDigit(char c)
去判断是否是数字, 查看JDK8文档
Some Unicode character ranges that contain digits: '\u0030' through '\u0039', ISO-LATIN-1 digits ('0' through '9') '\u0660' through '\u0669', Arabic-Indic digits '\u06F0' through '\u06F9', Extended Arabic-Indic digits '\u0966' through '\u096F', Devanagari digits '\uFF10' through '\uFF19', Fullwidth digits
原来Unicode
字符集中还有其他编码范围也是表示数字,做一下编码转换,这些数字如下
Arabic-Indic digits '٠' '١' '٢' '٣' '٤' '٥' '٦' '٧' '٨' '٩' Extended Arabic-Indic digits '۰' '۱' '۲' '۳' '۴' '۵' '۶' '۷' '۸' '۹', Devanagari digits '०' '१' '२' '३' '४' '५' '६' '७' '८' '९', Fullwidth digits '0' '1' '2' '3' '4' '5' '6' '7' '8' '9'
判断字符串是否是一个十进制数
调用BigDecimal
的单个String
参数的构造器方法,可以判断该字符串是否是数字
查看测试代码
import java.math.BigDecimal; public class Test { public static void main(String[] args) { String[] strArr = { "123", "123.1", " 1.0", "123..1", "abc", "1.1 ", "00.01", "001.01", "0101", "0x10" }; for (String s : strArr) { try { BigDecimal bigDecimal = new BigDecimal(s); System.out.println(s + "是一个数字, 转换后的BigDecimal是" + bigDecimal); } catch (NumberFormatException e) { System.out.println(s + "不是一个数字"); } } } }
查看输出结果
123是一个数字, 转换后的BigDecimal是123 123.1是一个数字, 转换后的BigDecimal是123.1 1.0不是一个数字 123..1不是一个数字 abc不是一个数字 1.1 不是一个数字 00.01是一个数字, 转换后的BigDecimal是0.01 001.01是一个数字, 转换后的BigDecimal是1.01 0101是一个数字, 转换后的BigDecimal是101 0x10不是一个数字
00.01
,001.01
,0101
这三个数字也判断是数字,前置多余的零忽略去掉了
这篇关于BigDecimal类中的String参数类型的构造器(Java)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-11有哪些好用的家政团队管理工具?
- 2025-01-11营销人必看的GTM五个指标
- 2025-01-11办公软件在直播电商前期筹划中的应用与推荐
- 2025-01-11提升组织效率:上级管理者如何优化跨部门任务分配
- 2025-01-11酒店精细化运营背后的协同工具支持
- 2025-01-11跨境电商选品全攻略:工具使用、市场数据与选品策略
- 2025-01-11数据驱动酒店管理:在线工具的核心价值解析
- 2025-01-11cursor试用出现:Too many free trial accounts used on this machine 的解决方法
- 2025-01-11百万架构师第十四课:源码分析:Spring 源码分析:深入分析IOC那些鲜为人知的细节|JavaGuide
- 2025-01-11不得不了解的高效AI办公工具API