001,浮点计算
Java中的简单类型是不适用于浮点(float,double)的精确计算的。原因:虽然现在的CPU都支持浮点的运算的,但CPU在处理的时候,也是先把浮点数转成整数再转成二进制,然后再进行操作,如果有取余,会有不同的取余方式。再加上运算完成后,再把二进制转换成上层的浮点,又会有一些取舍。就造成了了一些简单明显的错误。如
double a = 0.05; double b = 0.01; System.out.println(a+b);//这里会打印0.060000000000000005
解决方案:BCD码,或者,BigDecimal(java.math包下)
BigDecimal是java提供的不可变的,任意精度的有符号十进制数。
BigDecimal(double val)这个构造方法有一定的不要预知性。所以推荐用BigDecimal(String val)。
BigDecimal对象常用方法有:add,subtract,multiply,divide
如:
BigDecimal bd1 = new BigDecimal(0.05); BigDecimal bd2 = BigDecimal(0.01); System.out.println(bd1.add(bd2));//这里就会打印正确的:0.06
有用的工具类,对常用的浮点计算进行了简单的包装:
public class Arith{ //默认除法运算精度 private static final int DEF_SCALE = 10; //这个类不能实例化 private Arith(){ } /** * 提供精确的加法运算。 * @param v1 被加数 * @param v2 加数 * @return 两个参数的和 */ public static double add(double v1,double v2){ BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.add(b2).doubleValue(); } /** * 提供精确的减法运算。 * @param v1 被减数 * @param v2 减数 * @return 两个参数的差 */ public static double sub(double v1,double v2){ BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.subtract(b2).doubleValue(); } /** * 提供精确的乘法运算。 * @param v1 被乘数 * @param v2 乘数 * @return 两个参数的积 */ public static double mul(double v1,double v2){ BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.multiply(b2).doubleValue(); } /** * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 * 小数点以后10位,以后的数字四舍五入。 * @param v1 被除数 * @param v2 除数 * @return 两个参数的商 */ public static double div(double v1,double v2){ return div(v1,v2,DEF_SCALE); } /** * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 * 定精度,以后的数字四舍五入。 * @param v1 被除数 * @param v2 除数 * @param scale 表示表示需要精确到小数点以后几位。 * @return 两个参数的商 */ public static double div(double v1,double v2,int scale){ if(scale<0){ throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } /** * 提供精确的小数位四舍五入处理。 * @param v 需要四舍五入的数字 * @param scale 小数点后保留几位 * @return 四舍五入后的结果 */ public static double round(double v,int scale){ if(scale<0){ throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b = new BigDecimal(Double.toString(v)); BigDecimal one = new BigDecimal("1"); return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } }
002,对象排序
让JAVA对象排序有2种方式,
1,让待排序的对象实现Comparable接口,并实现其中的compareTo方法。
2,排序的时候,匿名实现Comparator接口,定制排序规则(灵活好用)
//按时时倒序排序 Collections.sort(list,new Comparator<ShopGroupInfo>() { public int compare(ShopGroupInfo a,ShopGroupInfo b) { long offset = a.getGmtCreate().getTime()-b.getGmtCreate().getTime(); return (offset>=0) ? -1 : 1; } }); //这里有个返回值意义问题,比较容易弄混淆。可以这样记:在你希望的排序条件下,返回-1。否则返回 。因为在数轴上,-1也在1的前面。如:对一批User排序,希望年龄大的排在前面,这样写: if(user1.getAge()>user2.getAge()){ return -1; }else{ return 1; }
003,获取本机名
public static String getServerName() { try { InetAddress addr = InetAddress.getLocalHost(); String ip = addr.getHostAddress(); String host = addr.getHostName().toString();// 获得本机名称 return ip; } catch (Exception e) { return "未知"; } }