javamysql 金额类型 什么类型 begdecimail

BigDecimal: subtract(BigDecimal subtrahend) : BigDecimal&&&java.math&&&Java by APIBigDecimal: subtract(BigDecimal subtrahend)
import java.math.BigD
public class MainClass {
public static void main(String argv[]) {
BigDecimal first = new BigDecimal("7.23343");
BigDecimal second = new BigDecimal("2.0");
System.out.println(first.add(second));
System.out.println(first.subtract(second));
System.out.println(first.divide(second));
System.out.println(first.equals(second));
System.out.println(first.abs());
System.out.println(first.max(second));
System.out.println(first.min(second));
System.out.println(first.remainder(second));
Related examples in the same category1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.
&|&Email:info &|&& Demo Source and Support. All rights reserved.java BigDecimal subraction failing - Stack Overflow
to customize your list.
Announcing Stack Overflow Documentation
We started with Q&A. Technical documentation is next, and we need your help.
Whether you're a beginner or an experienced developer, you can contribute.
I tried the following code. but getting different result when subtracting using BigDecimal.
double d1 = 0.1;
double d2 = 0.1;
System.out.println("double result: "+ (d2-d1));
float f1 = 0.1F;
float f2 = 0.1F;
System.out.println("float result: "+ (f2-f1));
BigDecimal b1 = new BigDecimal(0.01);
BigDecimal b2 = new BigDecimal(0.01);
b1 = b1.subtract(b2);
System.out.println("BigDecimal result: "+ b1);
double result: 0.0
float result: 0.0
BigDecimal result: 0E-59
I am still working on this. can anyone please clarify.
Interesting, the values appear to be equal and subtraction does give you zero, it appears to just be an issue with the printing code. The following code:
import java.math.BigD
public class Test {
public static void main(String args[]) {
BigDecimal b1 = new BigDecimal(0.01);
BigDecimal b2 = new BigDecimal(0.01);
BigDecimal b3 = new BigDecimal(0);
if (b1.compareTo(b2) == 0) System.out.println("equal 1");
b1 = b1.subtract(b2);
if (b1.compareTo(b3) == 0) System.out.println("equal 2");
System.out.println("BigDecimal result: "+ b1);
outputs both equal messages, indicating that the values are the same and that you get zero when you subtract.
You could try to raise this as a bug and see what Oracle comes back with. It's likely they'll just state that 0e-59 is still zero, so not a bug, or that the rather complex behaviour being described on the
is working as intended. Specifically, the point that states:
There is a one-to-one mapping between the distinguishable BigDecimal values and the result of this conversion. That is, every distinguishable BigDecimal value (unscaled value and scale) has a unique string representation as a result of using toString. If that string representation is converted back to a BigDecimal using the BigDecimal(String) constructor, then the original value will be recovered.
That fact that the original value needs to be recoverable means that toString() needs to generate a unique string for each scale, which is why you're getting 0e-59. Otherwise, converting the string back to a BigDecimal may give you a different value (unscaled-value/scale tuple).
If you really want zero to show up as "0" regardless of the scale, you can use something like:
if (b1.compareTo(BigDecimal.ZERO) == 0) b1 = new BigDecimal(0);
483k1159641411
[There are a lot of answers here telling you that binary floating-point can't exactly represent 0.01, and implying that the result you're seeing is somehow inexact.
Whilst the first part of that is true, it's not really the core issue here.]
The answer is that "0E-59" is equal to 0.
Recall that a BigDecimal is the combination of an unscaled value and a decimal scale factor:
System.out.println(b1.unscaledValue());
System.out.println(b1.scale());
The unscaled value is 0, as expected.
The "strange" scale value is simply an artifact of the decimal expansion of the non-exact floating-point representation of 0.01:
System.out.println(b2.unscaledValue());
System.out.println(b2.scale());
The next obvious question is, why doesn't BigDecimal.toString just display b1 as "0", for convenience?
The answer is that the string representation needs to be unambiguous.
From the :
There is a one-to-one mapping between the distinguishable BigDecimal values and the result of this conversion. That is, every distinguishable BigDecimal value (unscaled value and scale) has a unique string representation as a result of using toString. If that string representation is converted back to a BigDecimal using the BigDecimal(String) constructor, then the original value will be recovered.
If it just displayed "0", then you wouldn't be able to get back to this exact BigDecimal object.
183k20360513
Use constructor from String: b1 = new BigDecimal("0.01");
(slide 23)
You have to get the return value:
BigDecimal b3 = b1.subtract(b2);
System.out.println("BigDecimal result: "+ b3);
1.The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a
BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with
a scale of 1), but it is actually equal to
0.1015625. This is because 0.1 cannot be represented exactly as a double (or, for that
matter, as a binary fraction of any finite length). Thus, the value
that is being passed in to the constructor is not exactly equal to
0.1, appearances notwithstanding.
2.The String constructor, on the other hand, is perfectly predictable: writing new BigDecimal("0.1") creates a BigDecimal which is exactly
equal to 0.1, as one would expect. Therefore, it is generally
recommended that the String constructor be used in preference to this
3.When a double must be used as a source for a BigDecimal, note that this constructor provides it does not give the
same result as converting the double to a String using the
Double.toString(double) method and then using the BigDecimal(String)
constructor. To get that result, use the static valueOf(double)
So the real question is: with the following code,
BigDecimal b1 = new BigDecimal(0.01);
BigDecimal b2 = new BigDecimal(0.01);
b1 = b1.subtract(b2);
why does b1.toString() evaluate to "0E-59" and not to something like "0.0", "0E0" or just "0"?
The reason is that toString() prints the canonical format of the BigDecimal. See
for more information.
At the end, 0E-59 is 0.0 - it is 0*10^59 which mathematically evaluates to 0. So, the unexpected result is a matter of the internal representation of the BigDecimal.
To get the float or double values, use
b1.floatValue());
b1.doubleValue());
Both evaluate to 0.0.
24.3k44783
It's a known issue, BigDecimal(double val) API The results of this constructor can be somewhat unpredictable. Though it looks really wierd in this interpertation. Actual reason is that new BigDecimal(0.01) produces a BigDecimal with approx values
which has a long precision, and so the result of subtract has a long precision too.
Anyway, we can solves the "problem" this way
BigDecimal b1 = new BigDecimal("0.01");
BigDecimal b2 = new BigDecimal("0.01");
or we can use a constructor with setting a precision
BigDecimal b1 = new BigDecimal(0.01, new MathContext(1));
BigDecimal b2 = new BigDecimal(0.01, new MathContext(1));
78.4k1188160
Your Answer
Sign up or
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Post as a guest
By posting your answer, you agree to the
Not the answer you're looking for?
Browse other questions tagged
The week's top questions and answers
Important community announcements
Questions that need answers
By subscribing, you agree to the
Stack Overflow works best with JavaScript enabledBigDecimal, Groovy, and the Non-terminating Decimal Expansion | JavaWorld
Insider email
A software developer's public collection of tips and tricks, real-world solutions, and industry commentary related to Java programming.
BigDecimal, Groovy, and the Non-terminating Decimal Expansion
More like this
on IDG Answers
Use commas to separate multiple email addresses
Not all Java developers need the precision that
offers. However, those who do usually don't have to use BigDecimal for very long before running into the
with message "Non-terminati no exact representable decimal result."
provides an
of what this exception is, why it is thrown with some
operations on BigDecimal instances, and how to avoid it. In this blog post, I only briefly look at the issue from a Java perspective before moving onto how
handles it.
The following simple code snippet demonstrates how easy it is to encounter this ArithmeticException when dividing BigDecimal instances. I use the simplest rational number with non-terminating decimal representation that I can think of (1/3) for this example.
Main.java Demonstrating Arithmetic Exception on BigDecimal.dividepackage dustin.
import java.math.BigD
import static java.lang.System.
public class Main
public static void main(final String[] arguments)
final BigDecimal dividend = new BigDecimal("1");
final BigDecimal divisor = new BigDecimal("3");
out.println("1/3 = " + dividend.divide(divisor));
When the above code is executed, the expected exception is encountered as shown in the next screen snapshot (and listed after that image in text).
The text version of the above screen snapshot is shown next.Exception in thread "main" java.lang.ArithmeticException: Non-terminati no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1616)
at dustin.examples.Main.main(Main.java:13)
It is well-known among Groovy developers that Groovy automatically and implicitly often uses BigDecimal for any floating-point numbers. So, does Groovy run into this same problem? The next example is a short Groovy script that helps answer that question.
demoBigDecimalDivide.groovy #!/usr/bin/env groovy
def dividend = 1.0
def divisor = 3.0
def quotient = dividend / divisor
println "1/3 = ${quotient}"
Although it's not the point of this particular post, it's difficult to not notice how succinct the Groovy code is. I don't show it here, but if I printed out the .getClass() results on the three defined numerals in this script, they'd all come back as java.math.BigDecimal. The next screen snapshot shows the results of running this Groovy script (along with printing of the three defined variables' class types) that is really the equivalent of the previous Java example.
The Groovy script does not throw an exception! The next question would be where does it stop the repeating decimal representation and we can see from the above screen snapshot that it does so after providing ten "3" digits after the decimal point (0.).
There are often times when not using Groovy that it is advantageous to have a rounded representation of a quotient rather than an ArithmeticException when the quotient cannot be represented exactly. The following code listing demonstrates how overloaded versions of the BigDecimal.divide methods can be used to obtain a rounded answer.
Main.java Demonstrating Overloaded Versions of BigDecimal.dividepackage dustin.
import java.math.BigD
import java.math.RoundingM
import static java.lang.System.
* Demonstrates use of some of the overloaded BigDecimal.divide() methods with
* specific focus on using scale and rounding mode to avoid ArithmeticException
* when an exact quotient representation is not available.
public class Main
* Perform BigDecimal division without specifying scale or rounding.
* @param dividend Dividend in division.
* @param divisor Divisor in division.
* @return Quotient from dividing returns null if the
requested division results in a non-terminating representation.
public static BigDecimal performBigDecimalDivisionWithoutScaleOrRounding(
final BigDecimal dividend, final BigDecimal divisor)
BigDecimal quotient =
quotient = dividend.divide(divisor);
catch(ArithmeticException arithEx)
out.print(dividend.toPlainString() + "/" + divisor.toPlainString() + ": ");
out.println("leads to this exception: ");
out.println("\t" + arithEx.toString());
* Perform BigDecimal division of specified divisor by specified dividend and
* using provided RoundingMode. Note that a RoundingMode of UNNECESSARY could
* potentially lead to an ArithmeticException if the quotient cannot be
* represented exactly or if the provided divisor is zero.
* @param dividend Dividend in division.
* @param divisor Divisor in division.
* @param rounding Rounding Mode to be used in division if exact representation
cannot be obtained with provided scale (UNNECESSARY could lead to an
ArithmeticException being thrown).
* @return Quotient from dividing returns null if the
requested division results in a non-terminating representation.
* @throw ArithmeticException Thrown if the divisor is zero or if the quotient
cannot be represented exactly and the provided RoundingMode is
UNNECESSARY.
public static BigDecimal performBigDecimalDivisionWithSpecifiedRounding(
final BigDecimal dividend, final BigDecimal divisor, final RoundingMode rounding)
return dividend.divide(divisor, rounding);
* Perform BigDecimal division of specified divisor by specified dividend and
* using provided RoundingMode and provided scale. Note that a RoundingMode
* of UNNECESSARY could potentially lead to an ArithmeticException if the
* quotient cannot be represented exactly or if the provided divisor is zero.
* @param dividend Dividend in division.
* @param divisor Divisor in division.
* @param scale Scale of quotient.
* @param rounding Rounding Mode to be used in division if exact representation
cannot be obtained with provided scale (UNNECESSARY could lead to an
ArithmeticException being thrown).
* @return Quotient from dividing returns null if the
requested division results in a non-terminating representation.
* @throw ArithmeticException Thrown if the divisor is zero or if the quotient
cannot be represented exactly and the provided RoundingMode is
UNNECESSARY.
public static BigDecimal performBigDecimalDivisionWithSpecifiedRoundingAndScale(
final BigDecimal dividend, final BigDecimal divisor,
final int scale, final RoundingMode rounding)
return dividend.divide(divisor, scale, rounding);
* Main driver of demonstration of overloaded BigDecimal.divide methods.
* @param arguments Command line arguments: none expected.
public static void main(final String[] arguments)
final BigDecimal one = new BigDecimal("1");
final BigDecimal two = new BigDecimal("2");
final BigDecimal three = new BigDecimal("3");
final BigDecimal zero = new BigDecimal("0");
out.println("1/3 = " + performBigDecimalDivisionWithoutScaleOrRounding(one, three));
out.println("2/0 = " + performBigDecimalDivisionWithoutScaleOrRounding(two, zero));
out.println("1/3 = " + performBigDecimalDivisionWithSpecifiedRounding(one, three, RoundingMode.HALF_UP));
for (int i = 0 ; i & 15; i++)
out.println(
"1/3 [scale " + i + "] = "
+ performBigDecimalDivisionWithSpecifiedRoundingAndScale(
one, three, i, RoundingMode.HALF_UP));
for (int i = 0 ; i & 15; i++)
out.println(
"2/3 [scale " + i + "] = "
+ performBigDecimalDivisionWithSpecifiedRoundingAndScale(
two, three, i, RoundingMode.HALF_UP));
The output from running the above is shown next.
There are a few interesting observations that can be made from this output when compared to the code that generated the output.
is thrown when
cannot generate an exact representation and there is no rounding used or rounding type of
is specified.
An ArithmeticException is also thrown by the overloaded versions of BigDecimal.divide when the
(cannot ).
The effects of
are shown for quotients that cannot be represented exactly. Although only
is used, it does demonstrate those effects by representing both 1/3 and 2/3.
The effects of scale are dramatically demonstrated via iterations of 15 different scales from 0 to 14. From this, we can see that Groovy implicitly used a scale of 10 rather than throwing an ArithmeticException.
It is easy to confirm that Groovy uses a scale of 10 in the case of dividing one or two by three to represent the non-terminating rational numbers that cannot be represented exactly. The revised Groovy script does this.
#!/usr/bin/env groovy
def one = 1.0
def two = 2.0
def three = 3.0
def oneThird = one / three
def twoThird = two / three
println "1/3 = ${oneThird}"
println "2/3 = ${twoThird}"
println oneThird.dump()
println twoThird.dump()
The output from running this script (shown in the next screen snapshot) proves that the scale is 10 and that the rounding mode is one that allows for 1/3 to end with a "3" and for 2/3 to end with a "7."
, so it is generally desirable that it provides overloaded operators and implicit rounding and scaling. However, there may be cases where one needs a different level of scaling. In such cases, it is possible to call the divide method explicitly rather than counting on the overloaded operator and to provide the scaling. This is demonstrated in the next Groovy code listing.
#!/usr/bin/env groovy
import static java.math.RoundingMode.HALF_UP
def one = 1.0
def two = 2.0
def three = 3.0
def oneThird = one.divide(three, 15, HALF_UP)
def twoThird = two.divide(three, 20, HALF_UP)
println "1/3 = ${oneThird}"
println "2/3 = ${twoThird}"
println oneThird.dump()
println twoThird.dump()
The output from the above is shown in the next screen snapshot, which includes the output from the previous run as well for easy comparison.
There might be a situation in which the developer actually wants an ArithmeticException to be thrown to indicate that an exact representation is not available for a division call. This can be enforced in Groovy by making an explicit divide call (via method name rather than overloaded / operator) and providing a rounding mode of UNNECESSARY as shown in the next code listing (assumes local variables one and three as defined above).
def exception = one.divide(three, 10, RoundingMode.UNNECESSARY)
When executed, the ArithmeticException is encountered with a messages simply stating "Rounding necessary." This is shown in the next screen snapshot.
Conclusion
Java's BigDecimal is handy when one desires better precision than double or float can support. However, it must throw an ArithmeticException when a quotient result of one of the overloaded BigDecimal.divide calls cannot be represented exactly so that client code does not presume that the quotient provided is an exactly representation. Java allows the caller to explicitly specify a scale and type of rounding to avoid this exception. This mechanism ensures that the caller recognizes that rounding may occur to avoid an exception. The caller gets to specify the rules of that rounding and of the scale.
Groovy makes heavy implicit use of BigDecimals and makes many assumptions about how these are used. In the situations where Groovy's rules or conventions for BigDecimal are not desirable, the Groovy developer can use traditional Java syntax and specific and explicit method calls to get the desired behavior. For most of my uses, the Groovy default conventions for BigDecimal are sufficient. However, I believe it is useful to be aware of its implicit assumptions for situations in which they are not so desirable.Original posting available at
(Inspired by Actual Events)
White Paper
White Paper
Popular on JavaWorld
Learn how to use subtype polymorphism to execute different forms of the same Java method
Newsletters Stay up to date on the latest tutorials and Java community news posted on JavaWorld Get our Enterprise Java newsletter
This baker's dozen of lean and mean Node.js frameworks can help streamline your development of fast...
Built for realtime, Kafka scales horizontally and offers much higher throughput than some traditional...
Popular Resources
White Paper
White Paper
White Paper
Featured Stories
Find out what to look for in a Java IDE and get tips for deciding which of the top three is best for...
The tool has shed its Java dependency in favor of compiling Java source code to JavaScript
Docker brings consistency and repeatability to large and fast-moving environments, but not without...
There are always new programming niches to fill and needs to be met. Coconut, Crystal, and Oden's...

我要回帖

更多关于 数据库金额用什么类型 的文章

 

随机推荐