﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-心中海的程序人生</title><link>http://www.blogjava.net/jamespace/</link><description>技术不是学出来的，而是总结出来的</description><language>zh-cn</language><lastBuildDate>Fri, 17 Apr 2026 22:40:03 GMT</lastBuildDate><pubDate>Fri, 17 Apr 2026 22:40:03 GMT</pubDate><ttl>60</ttl><item><title>eclipse提示功能不见了!</title><link>http://www.blogjava.net/jamespace/archive/2008/05/27/203080.html</link><dc:creator>心中海</dc:creator><author>心中海</author><pubDate>Mon, 26 May 2008 16:52:00 GMT</pubDate><guid>http://www.blogjava.net/jamespace/archive/2008/05/27/203080.html</guid><wfw:comment>http://www.blogjava.net/jamespace/comments/203080.html</wfw:comment><comments>http://www.blogjava.net/jamespace/archive/2008/05/27/203080.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/jamespace/comments/commentRss/203080.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jamespace/services/trackbacks/203080.html</trackback:ping><description><![CDATA[今天使用eclipse时,不知按了哪个快捷键，发现提示功能不见了，好棘手，还好解决了：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; windows-&gt;preference-&gt;java-&gt;Editor-&gt;content Assist-&gt;Advance&nbsp;根据需要选择右边的选项就 OK 了。<br />
<br />
......
<img src ="http://www.blogjava.net/jamespace/aggbug/203080.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jamespace/" target="_blank">心中海</a> 2008-05-27 00:52 <a href="http://www.blogjava.net/jamespace/archive/2008/05/27/203080.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java.math.BigDecimal的用法？（转载）</title><link>http://www.blogjava.net/jamespace/archive/2007/12/19/BigDecimal.html</link><dc:creator>心中海</dc:creator><author>心中海</author><pubDate>Wed, 19 Dec 2007 06:40:00 GMT</pubDate><guid>http://www.blogjava.net/jamespace/archive/2007/12/19/BigDecimal.html</guid><wfw:comment>http://www.blogjava.net/jamespace/comments/168747.html</wfw:comment><comments>http://www.blogjava.net/jamespace/archive/2007/12/19/BigDecimal.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jamespace/comments/commentRss/168747.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jamespace/services/trackbacks/168747.html</trackback:ping><description><![CDATA[标题&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在Java中实现浮点数的精确计算&nbsp;&nbsp;&nbsp;&nbsp;AYellow（原作）&nbsp;修改&nbsp;&nbsp;&nbsp;&nbsp;<br />
关键字&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java&nbsp;浮点数&nbsp;精确计算&nbsp;&nbsp;&nbsp;<br />
<br />
问题的提出：<br />
如果我们编译运行下面这个程序会看到什么？<br />
public&nbsp;class&nbsp;Test{<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String&nbsp;args[]){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(0.05+0.01);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(1.0-0.42);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(4.015*100);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(123.3/100);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
};<br />
你没有看错！结果确实是<br />
0.060000000000000005<br />
0.5800000000000001<br />
401.49999999999994<br />
1.2329999999999999<br />
Java中的简单浮点数类型float和double不能够进行运算。不光是Java，在其它很多编程语言中也有这样的问题。在大多数情况下，计算的结果是准确的，但是多试几次（可以做一个循环）就可以试出类似上面的错误。现在终于理解为什么要有BCD码了。<br />
这个问题相当严重，如果你有9.999999999999元，你的计算机是不会认为你可以购买10元的商品的。<br />
在有的编程语言中提供了专门的货币类型来处理这种情况，但是Java没有。现在让我们看看如何解决这个问题。<br />
&nbsp;<br />
四舍五入<br />
我们的第一个反应是做四舍五入。Math类中的round方法不能设置保留几位小数，我们只能象这样（保留两位）：<br />
public&nbsp;double&nbsp;round(double&nbsp;value){<br />
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Math.round(value*100)/100.0;<br />
}<br />
非常不幸，上面的代码并不能正常工作，给这个方法传入4.015它将返回4.01而不是4.02，如我们在上面看到的<br />
4.015*100=401.49999999999994<br />
因此如果我们要做到精确的四舍五入，不能利用简单类型做任何运算<br />
java.text.DecimalFormat也不能解决这个问题：<br />
System.out.println(new&nbsp;java.text.DecimalFormat("0.00").format(4.025));<br />
输出是4.02<br />
&nbsp;<br />
BigDecimal<br />
在《Effective&nbsp;Java》这本书中也提到这个原则，float和double只能用来做科学计算或者是工程计算，在商业计算中我们要用java.math.BigDecimal。BigDecimal一共有4个够造方法，我们不关心用BigInteger来够造的那两个，那么还有两个，它们是：<br />
BigDecimal(double&nbsp;val)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Translates&nbsp;a&nbsp;double&nbsp;into&nbsp;a&nbsp;BigDecimal.&nbsp;<br />
BigDecimal(String&nbsp;val)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Translates&nbsp;the&nbsp;String&nbsp;repre&nbsp;sentation&nbsp;of&nbsp;a&nbsp;BigDecimal&nbsp;into&nbsp;a&nbsp;BigDecimal.<br />
上面的API简要描述相当的明确，而且通常情况下，上面的那一个使用起来要方便一些。我们可能想都不想就用上了，会有什么问题呢？等到出了问题的时候，才发现上面哪个够造方法的详细说明中有这么一段：<br />
Note:&nbsp;the&nbsp;results&nbsp;of&nbsp;this&nbsp;constructor&nbsp;can&nbsp;be&nbsp;somewhat&nbsp;unpredictable.&nbsp;One&nbsp;might&nbsp;assume&nbsp;that&nbsp;new&nbsp;BigDecimal(.1)&nbsp;is&nbsp;exactly&nbsp;equal&nbsp;to&nbsp;.1,&nbsp;but&nbsp;it&nbsp;is&nbsp;actually&nbsp;equal&nbsp;to&nbsp;.1000000000000000055511151231257827021181583404541015625.&nbsp;This&nbsp;is&nbsp;so&nbsp;because&nbsp;.1&nbsp;cannot&nbsp;be&nbsp;represented&nbsp;exactly&nbsp;as&nbsp;a&nbsp;double&nbsp;(or,&nbsp;for&nbsp;that&nbsp;matter,&nbsp;as&nbsp;a&nbsp;binary&nbsp;fraction&nbsp;of&nbsp;any&nbsp;finite&nbsp;length).&nbsp;Thus,&nbsp;the&nbsp;long&nbsp;value&nbsp;that&nbsp;is&nbsp;being&nbsp;passed&nbsp;in&nbsp;to&nbsp;the&nbsp;constructor&nbsp;is&nbsp;not&nbsp;exactly&nbsp;equal&nbsp;to&nbsp;.1,&nbsp;appearances&nbsp;nonwithstanding.&nbsp;<br />
The&nbsp;(String)&nbsp;constructor,&nbsp;on&nbsp;the&nbsp;other&nbsp;hand,&nbsp;is&nbsp;perfectly&nbsp;predictable:&nbsp;new&nbsp;BigDecimal(".1")&nbsp;is&nbsp;exactly&nbsp;equal&nbsp;to&nbsp;.1,&nbsp;as&nbsp;one&nbsp;would&nbsp;expect.&nbsp;Therefore,&nbsp;it&nbsp;is&nbsp;generally&nbsp;recommended&nbsp;that&nbsp;the&nbsp;(String)&nbsp;constructor&nbsp;be&nbsp;used&nbsp;in&nbsp;preference&nbsp;to&nbsp;this&nbsp;one.<br />
原来我们如果需要精确计算，非要用String来够造BigDecimal不可！在《Effective&nbsp;Java》一书中的例子是用String来够造BigDecimal的，但是书上却没有强调这一点，这也许是一个小小的失误吧。<br />
&nbsp;<br />
解决方案<br />
现在我们已经可以解决这个问题了，原则是使用BigDecimal并且一定要用String来够造。<br />
但是想像一下吧，如果我们要做一个加法运算，需要先将两个浮点数转为String，然后够造成BigDecimal，在其中一个上调用add方法，传入另一个作为参数，然后把运算的结果（BigDecimal）再转换为浮点数。你能够忍受这么烦琐的过程吗？下面我们提供一个工具类Arith来简化操作。它提供以下静态方法，包括加减乘除和四舍五入：<br />
public&nbsp;static&nbsp;double&nbsp;add(double&nbsp;v1,double&nbsp;v2)<br />
public&nbsp;static&nbsp;double&nbsp;sub(double&nbsp;v1,double&nbsp;v2)<br />
public&nbsp;static&nbsp;double&nbsp;mul(double&nbsp;v1,double&nbsp;v2)<br />
public&nbsp;static&nbsp;double&nbsp;div(double&nbsp;v1,double&nbsp;v2)<br />
public&nbsp;static&nbsp;double&nbsp;div(double&nbsp;v1,double&nbsp;v2,int&nbsp;scale)<br />
public&nbsp;static&nbsp;double&nbsp;round(double&nbsp;v,int&nbsp;scale)<br />
附录<br />
源文件Arith.java：<br />
import&nbsp;java.math.BigDecimal;<br />
/**<br />
&nbsp;*&nbsp;由于Java的简单类型不能够精确的对浮点数进行运算，这个工具类提供精<br />
&nbsp;*&nbsp;确的浮点数运算，包括加减乘除和四舍五入。<br />
&nbsp;*/<br />
public&nbsp;class&nbsp;Arith{<br />
&nbsp;&nbsp;&nbsp;&nbsp;//默认除法运算精度<br />
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;final&nbsp;int&nbsp;DEF_DIV_SCALE&nbsp;=&nbsp;10;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//这个类不能实例化<br />
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;Arith(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;提供精确的加法运算。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;v1&nbsp;被加数<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;v2&nbsp;加数<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;两个参数的和<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;double&nbsp;add(double&nbsp;v1,double&nbsp;v2){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;b1&nbsp;=&nbsp;new&nbsp;BigDecimal(Double.toString(v1));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;b2&nbsp;=&nbsp;new&nbsp;BigDecimal(Double.toString(v2));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;b1.add(b2).doubleValue();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;提供精确的减法运算。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;v1&nbsp;被减数<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;v2&nbsp;减数<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;两个参数的差<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;double&nbsp;sub(double&nbsp;v1,double&nbsp;v2){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;b1&nbsp;=&nbsp;new&nbsp;BigDecimal(Double.toString(v1));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;b2&nbsp;=&nbsp;new&nbsp;BigDecimal(Double.toString(v2));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;b1.subtract(b2).doubleValue();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;提供精确的乘法运算。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;v1&nbsp;被乘数<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;v2&nbsp;乘数<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;两个参数的积<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;double&nbsp;mul(double&nbsp;v1,double&nbsp;v2){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;b1&nbsp;=&nbsp;new&nbsp;BigDecimal(Double.toString(v1));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;b2&nbsp;=&nbsp;new&nbsp;BigDecimal(Double.toString(v2));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;b1.multiply(b2).doubleValue();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;提供（相对）精确的除法运算，当发生除不尽的情况时，精确到<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;小数点以后10位，以后的数字四舍五入。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;v1&nbsp;被除数<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;v2&nbsp;除数<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;两个参数的商<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;double&nbsp;div(double&nbsp;v1,double&nbsp;v2){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;div(v1,v2,DEF_DIV_SCALE);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;定精度，以后的数字四舍五入。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;v1&nbsp;被除数<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;v2&nbsp;除数<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;scale&nbsp;表示表示需要精确到小数点以后几位。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;两个参数的商<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;double&nbsp;div(double&nbsp;v1,double&nbsp;v2,int&nbsp;scale){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(scale&lt;0){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;IllegalArgumentException(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"The&nbsp;scale&nbsp;must&nbsp;be&nbsp;a&nbsp;positive&nbsp;integer&nbsp;or&nbsp;zero");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;b1&nbsp;=&nbsp;new&nbsp;BigDecimal(Double.toString(v1));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;b2&nbsp;=&nbsp;new&nbsp;BigDecimal(Double.toString(v2));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;提供精确的小数位四舍五入处理。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;v&nbsp;需要四舍五入的数字<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;scale&nbsp;小数点后保留几位<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;四舍五入后的结果<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;double&nbsp;round(double&nbsp;v,int&nbsp;scale){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(scale&lt;0){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;IllegalArgumentException(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"The&nbsp;scale&nbsp;must&nbsp;be&nbsp;a&nbsp;positive&nbsp;integer&nbsp;or&nbsp;zero");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;b&nbsp;=&nbsp;new&nbsp;BigDecimal(Double.toString(v));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigDecimal&nbsp;one&nbsp;=&nbsp;new&nbsp;BigDecimal("1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
};<br />
  <img src ="http://www.blogjava.net/jamespace/aggbug/168747.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jamespace/" target="_blank">心中海</a> 2007-12-19 14:40 <a href="http://www.blogjava.net/jamespace/archive/2007/12/19/BigDecimal.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>