aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorigerasim <unknown>2019-04-03 02:07:42 +0100
committerbell-sw <liberica@bell-sw.com>2019-04-20 16:52:23 +0300
commit488051350f9cb7bb6a4558d99646a69673d33087 (patch)
tree08a11bd2402dbb6238cbc9b59061dfc55e68bb71
parent036226f409f75a02331da2cf1f28f357d57c8a84 (diff)
downloadjdk8u_jdk-488051350f9cb7bb6a4558d99646a69673d33087.tar.gz
8211936: Better String parsing
Reviewed-by: aph
-rw-r--r--src/share/classes/java/math/BigDecimal.java50
1 files changed, 39 insertions, 11 deletions
diff --git a/src/share/classes/java/math/BigDecimal.java b/src/share/classes/java/math/BigDecimal.java
index 3bb81a660a..23ac74cddc 100644
--- a/src/share/classes/java/math/BigDecimal.java
+++ b/src/share/classes/java/math/BigDecimal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -3060,9 +3060,32 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @return this {@code BigDecimal} converted to a {@code long}.
*/
public long longValue(){
- return (intCompact != INFLATED && scale == 0) ?
- intCompact:
- toBigInteger().longValue();
+ if (intCompact != INFLATED && scale == 0) {
+ return intCompact;
+ } else {
+ // Fastpath zero and small values
+ if (this.signum() == 0 || fractionOnly() ||
+ // Fastpath very large-scale values that will result
+ // in a truncated value of zero. If the scale is -64
+ // or less, there are at least 64 powers of 10 in the
+ // value of the numerical result. Since 10 = 2*5, in
+ // that case there would also be 64 powers of 2 in the
+ // result, meaning all 64 bits of a long will be zero.
+ scale <= -64) {
+ return 0;
+ } else {
+ return toBigInteger().longValue();
+ }
+ }
+ }
+
+ /**
+ * Return true if a nonzero BigDecimal has an absolute value less
+ * than one; i.e. only has fraction digits.
+ */
+ private boolean fractionOnly() {
+ assert this.signum() != 0;
+ return (this.precision() - this.scale) <= 0;
}
/**
@@ -3080,15 +3103,20 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
public long longValueExact() {
if (intCompact != INFLATED && scale == 0)
return intCompact;
- // If more than 19 digits in integer part it cannot possibly fit
- if ((precision() - scale) > 19) // [OK for negative scale too]
- throw new java.lang.ArithmeticException("Overflow");
- // Fastpath zero and < 1.0 numbers (the latter can be very slow
- // to round if very small)
+
+ // Fastpath zero
if (this.signum() == 0)
return 0;
- if ((this.precision() - this.scale) <= 0)
+
+ // Fastpath numbers less than 1.0 (the latter can be very slow
+ // to round if very small)
+ if (fractionOnly())
throw new ArithmeticException("Rounding necessary");
+
+ // If more than 19 digits in integer part it cannot possibly fit
+ if ((precision() - scale) > 19) // [OK for negative scale too]
+ throw new java.lang.ArithmeticException("Overflow");
+
// round to an integer, with Exception if decimal part non-0
BigDecimal num = this.setScale(0, ROUND_UNNECESSARY);
if (num.precision() >= 19) // need to check carefully
@@ -3130,7 +3158,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
public int intValue() {
return (intCompact != INFLATED && scale == 0) ?
(int)intCompact :
- toBigInteger().intValue();
+ (int)longValue();
}
/**