`
King_XR
  • 浏览: 26613 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论
收藏列表
标题 标签 来源
JS解决浮点计算BUG终极解决办法
问题这样的:  
  
  37.5*5.5=206.08  (JS算出来是这样的一个结果,我四舍五入取两位小数)  
  
  我先怀疑是四舍五入的问题,就直接用JS算了一个结果为:206.08499999999998  
  
  怎么会这样,两个只有一位小数的数字相乘,怎么可能多出这么小数点出来。  
  
  我Google了一下,发现原来这是JavaScript浮点运算的一个bug。  
  
  比如:7*0.8 JavaScript算出来就是:5.6000000000000005  
  
  
  
  网上找到了一些解决办法,就是重新写了一些浮点运算的函数。  
  
  下面就把这些方法摘录下来,以供遇到同样问题的朋友参考:  
  
    
  
   程序代码  
   
   
  在你要用的地方包含这些函数,然后调用它来计算就可以了。  
  
  比如你要计算:7*0.8 ,则改成 (7).mul(8)   
  
  其它运算类似,就可以得到比较精确的结果。  
问题这样的:

  37.5*5.5=206.08  (JS算出来是这样的一个结果,我四舍五入取两位小数)

  我先怀疑是四舍五入的问题,就直接用JS算了一个结果为:206.08499999999998

  怎么会这样,两个只有一位小数的数字相乘,怎么可能多出这么小数点出来。

  我Google了一下,发现原来这是JavaScript浮点运算的一个bug。

  比如:7*0.8 JavaScript算出来就是:5.6000000000000005



  网上找到了一些解决办法,就是重新写了一些浮点运算的函数。

  下面就把这些方法摘录下来,以供遇到同样问题的朋友参考:

  

   程序代码
 
 
  在你要用的地方包含这些函数,然后调用它来计算就可以了。

  比如你要计算:7*0.8 ,则改成 (7).mul(8) 

  其它运算类似,就可以得到比较精确的结果。 

   看了很多关于解决javacsript浮点计算BUG办法,这个算是比较不错的了。但最终测试发现,加法还是有BUG

accAdd(0.0192, 0.12965)计算出来的结果0.14884999999999998,仍然存在问题。经过冷凝改写JS后,完美解决加法问题。

代码如下:

[javascript] view plaincopyprint?/** 
* javascript calc 
*  
* 描  述   :  JS浮点计算BUG屏蔽 
* 创建人   :  冷凝 
* 创建日期 :  2012-12-21更新,解决触发部分BUG 
*  
*/  
  
function accDiv(arg1, arg2) {  
  
    var t1 = 0, t2 = 0, t3 = 0, r1, r2;  
  
    try { t1 = arg1.toString().split(".")[1].length } catch (e) { }  
  
    try { t2 = arg2.toString().split(".")[1].length } catch (e) { }  
  
    r1 = Number(arg1.toString().replace(".", ""))  
  
    r2 = Number(arg2.toString().replace(".", ""))  
  
    if (r2 == 0)  
        return 0;  
  
    var result = String(r1 / r2);  
  
    try { t3 = result.toString().split(".")[1].length } catch (e) { }  
  
    var index = t2 - t1 - t3;  
  
    if (index < 0) {  
        result = result.replace(".", "");  
  
        while (result.length <= Math.abs(index)) {  
            result = '0' + result;  
        }  
  
        var start = result.substring(0, result.length + index);  
        var end = result.substring(result.length + index, result.length);  
  
        result = start + '.' + end;  
  
        return Number(result);  
    }  
    else if (index > 0) {  
        result = result.replace(".", "");  
  
        while (result.length <= Math.abs(index)) {  
            result += '0';  
        }  
        return Number(result);  
    }  
    else return Number(result.replace(".", ""));  
  
}  
  
  
//给Number类型增加一个div方法,调用起来更加方便。   
  
Number.prototype.div = function (arg) {  
    /// <summary>   
    ///     除法   
    /// </summary>   
    return accDiv(this, arg);  
  
}  
function accMul(arg1, arg2) {  
  
    var m = 0, s1 = arg1.toString(), s2 = arg2.toString();  
  
    try { m += s1.split(".")[1].length } catch (e) { }  
  
    try { m += s2.split(".")[1].length } catch (e) { }  
  
    return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m)  
  
}  
  
Number.prototype.mul = function (arg) {  
    /// <summary>   
    ///     乘法   
    /// </summary>   
    return accMul(arg, this);  
  
}  
  
function accAdd(arg1, arg2) {  
  
    var r1, r2, m, c;  
  
    try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }  
  
    try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }  
  
    c = Math.abs(r1 - r2);  
    m = Math.pow(10, Math.max(r1, r2))  
    if (c > 0) {  
        var cm = Math.pow(10, c);  
        if (r1 > r2) {  
            arg1 = Number(arg1.toString().replace(".", ""));  
            arg2 = Number(arg2.toString().replace(".", "")) * cm;  
        }  
        else {  
            arg1 = Number(arg1.toString().replace(".", "")) * cm;  
            arg2 = Number(arg2.toString().replace(".", ""));  
        }  
    }  
    else {  
        arg1 = Number(arg1.toString().replace(".", ""));  
        arg2 = Number(arg2.toString().replace(".", ""));  
    }  
    return (arg1 + arg2) / m  
  
}  
  
Number.prototype.add = function (arg) {  
    /// <summary>   
    ///     加法   
    /// </summary>   
    return accAdd(arg, this);  
  
}  
纯CSS去除超链接、按钮点击时的虚线框
<style type="text/css">  
    .wrap{position:relative;}  
    .btns{zoom:1;}  
    .btns *{outline:0;zoom:1;background:#f2f2f2;}  
    .btns button::-moz-focus-inner{border-color:transparent!important;}  
</style>  
<div class="wrap">
    <div class="btns">  
        <button type="button">确定</button><button type="button">取消</button>  
        <a href="#">确定</a><a href="#">取消</a>  
    </div>
</div>



1. firefox及标准浏览器下可以用css属性outline:
Html代码

<style> 
   a{outline:none;} /*0也可以*/
</style>

2. IE下如下实现(据说过多使用效率低):
Html代码    

a{blr:expression(this.onFocus=this.blur());}
彩色验证码生成技术
package com;

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@SuppressWarnings("serial")
public class PictureCheckCode extends HttpServlet {
	
	public PictureCheckCode() {
		super();
	}

	public void destroy() {
		super.destroy(); 
	}

	public void init() throws ServletException {
		super.init();
	}

	// 获取随机颜色
	public Color getRandColor(int s, int e) {
		Random random = new Random();
		if (s > 255) s = 255;
		if (e > 255) e = 255;
		int r = s + random.nextInt(e - s);		//随机生成RGB颜色中的r值
		int g = s + random.nextInt(e - s);		//随机生成RGB颜色中的g值
		int b = s + random.nextInt(e - s);		//随机生成RGB颜色中的b值
		return new Color(r, g, b);
	}

	public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setHeader("Pragma", "No-cache");
		response.setHeader("Cache-Control", "No-cache");
		response.setDateHeader("Expires", 0);
		// 指定生成的响应是图片
		response.setContentType("image/jpeg");
		int width = 80;
		int height = 22;
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		Graphics g = image.getGraphics();
		Graphics2D g2d = (Graphics2D) g;
		Random random = new Random();
		Font mFont = new Font("Times New Roman", Font.PLAIN, 22);
		g.setColor(getRandColor(200, 250));
		g.fillRect(0, 0, width, height);
		g.setFont(mFont);
		g.setColor(getRandColor(180, 200));
		// 画随机的线条
		for (int i = 0; i < 100; i++) {
			int x = random.nextInt(width - 1);
			int y = random.nextInt(height - 1);
			int x1 = random.nextInt(6) + 1;
			int y1 = random.nextInt(12) + 1;
			BasicStroke bs = new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL);
			Line2D line = new Line2D.Double(x, y, x + x1, y + y1);
			g2d.setStroke(bs);
			g2d.draw(line);
		}
		String sRand = "";
		String ctmp = "";
		int itmp = 0;
		for (int i = 0; i < 4; i++) {
			//random = new Random(new java.util.Date().getTime() + i);
			switch (random.nextInt(4)) {
				case 1:
					itmp = random.nextInt(26) + 65; // 生成A~Z的字母
					ctmp = String.valueOf((char) itmp);
					break;
				case 2: 
					itmp = random.nextInt(26) + 97; // 生成a~z的字母
					ctmp = String.valueOf((char) itmp);
					break;
				default:
					itmp = random.nextInt(10) + 48; // 生成0~9的数字
					ctmp = String.valueOf((char) itmp);
					break;
			}
			sRand += ctmp;
			Color color = new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110));
			g.setColor(color);
			
			// 将文字旋转指定角度
			Graphics2D g2d_word = (Graphics2D) g;
			AffineTransform trans = new AffineTransform();
			trans.rotate(random.nextInt(45) * 3.14 / 180, 15 * i + 8, 7);
			// 缩放文字
			float scaleSize = random.nextFloat() + 0.8f;
			if (scaleSize > 1f)	scaleSize = 1f;
			trans.scale(scaleSize, scaleSize);
			g2d_word.setTransform(trans);
			
			//文字输出的位置, 第二参数和第三个参数数分别是 x, y 坐标
			g.drawString(ctmp, 15 * i + 12, 16);
		}
		System.out.println("01工程生成的验证码: " + sRand);
		// 将生成的验证码保存到Session中
		HttpSession session = request.getSession(true);
		session.setAttribute("randCheckCode", sRand);
		g.dispose();
		ImageIO.write(image, "JPEG", response.getOutputStream());
	}
}
Myeclipse注册机实现
/**
 * 
 */
package com.xr.common;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;

/**
 * @作者 lixingren
 * @时间 2012-11-12 上午09:58:07
 * @描述 MyEclipse注册机实现
 */
public class MyEclipseRegister {

	private static final String L = "Decompiling this copyrighted software is a violation of both your license agreement and the Digital Millenium Copyright Act of 1998 (http://www.loc.gov/copyright/legislation/dmca.pdf). Under section 1204 of the DMCA, penalties range up to a $500,000 fine or up to five years imprisonment for a first offense. Think about it; pay for a license, avoid prosecution, and feel better about yourself.";

	static int decode(String s) {
		int i = 0;
		char[] ac = s.toCharArray();
		int j = 0;
		for (int k = ac.length; j < k; ++j)
			i = 31 * i + ac[j];

		return Math.abs(i);
	}

	static String change(String s) {
		if ((s == null) || (s.length() == 0))
			return s;
		byte[] abyte0 = s.getBytes();
		char[] ac = new char[s.length()];
		int i = 0;
		for (int k = abyte0.length; i < k; ++i) {
			int j = abyte0[i];
			if ((j >= 48) && (j <= 57))
				j = (j - 48 + 5) % 10 + 48;
			else if ((j >= 65) && (j <= 90))
				j = (j - 65 + 13) % 26 + 65;
			else if ((j >= 97) && (j <= 122))
				j = (j - 97 + 13) % 26 + 97;
			ac[i] = (char) j;
		}
		return String.valueOf(ac);
	}
	
	public static void main(String[] args) {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String userId = null;
		int intLicenseNum = 1;
		String strLicenseNum = null;
		boolean bProFlag = true;
		String strProFlag = null;

		while ((userId == null) || ("".equals(userId.trim()))) {
			System.out.print("用户名: ");
			try {
				userId = br.readLine();
			} catch (IOException ioe1) {
			}
		}
		System.out.print("注册码可用的用户数量(默认 1, 最大 999): ");
		try {
			strLicenseNum = br.readLine();
		} catch (IOException ioe2) {
		}

		Object nf = new DecimalFormat("000");
		if ((strLicenseNum == null) || ("".equals(strLicenseNum.trim())))
			strLicenseNum = ((NumberFormat) nf).format(intLicenseNum);
		else {
			strLicenseNum = ((NumberFormat) nf).format(Integer
					.parseInt(strLicenseNum));
		}

		System.out.print("个人版 或 标准版(默认 个人版, n 标准版): ");
		try {
			strProFlag = br.readLine();
		} catch (IOException ioe3) {
		}
		if ((strProFlag != null) && (!("".equals(strProFlag.trim())))) {
			bProFlag = false;
		}

		Calendar cal = Calendar.getInstance();
		cal.add(1, 2);
		cal.add(6, -1);
		SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");

		String need = userId.substring(0, 1) + "Y"
				+ ((bProFlag) ? "E3MP" : "E2MY") + "-100" + strLicenseNum + "-"
				+ sdf.format(cal.getTime()) + "0";
		String dx = need + L + userId;
		int suf = decode(dx);
		String code = need + suf;
		System.out.println("注册码: " + change(code));
	}
}
Java实现网络抓取HTML
public class RequestHtmlCode {
	
	public static byte[] readInputStream(InputStream instream) throws Exception {

		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		byte[] buffer = new byte[1204];
		int len = 0;
		while ((len = instream.read(buffer)) != -1) {
			outStream.write(buffer, 0, len);
		}
		instream.close();
		return outStream.toByteArray();
	}

	public static void main(String[] args) throws Exception {

		URL url = new URL("http://www.baidu.com");
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setRequestMethod("GET");
		conn.setConnectTimeout(5 * 1000);
		InputStream inStream = conn.getInputStream();//通过输入流获取html数据
		byte[] data = readInputStream(inStream);//得到html的二进制数据
		String html = new String(data);
		System.out.println(html);
	}
}
Log4j自动创建文件夹
public class MyDailyRollingFileAppender extends DailyRollingFileAppender {

    @Override
    public void setFile(String file) {
        String filePath = file;
        File fileCheck = new File(filePath);
        if (!fileCheck.exists())
            fileCheck.getParentFile().mkdirs();
        super.setFile(filePath);
    }

}
Java反射获取实体类的属性
package test;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * @作者 lixingren
 * @时间 2012-11-19 下午05:18:44
 * @描述 Java反射获取实体类的属性
 * @版本 V1.0
 * @修改人
 * @修改时间 
 * @修改原因
 */
public class Reflect {

	public static void testReflect(Object model) throws NoSuchMethodException,
			IllegalAccessException, IllegalArgumentException,
			InvocationTargetException {
		// 获取实体类的所有属性,返回Field数组
		Field[] field = model.getClass().getDeclaredFields();   
		for (int j = 0; j < field.length; j++) { //遍历所有属性
			String name = field[j].getName(); //获取属性的名字
			System.out.println("attribute name:" + name);
			// 将属性的首字符大写,方便构造get,set方法
			name = name.substring(0, 1).toUpperCase() + name.substring(1); 
			String type = field[j].getGenericType().toString(); //获取属性的类型
			// 如果type是类类型,则前面包含"class ",后面跟类名
			if (type.equals("class java.lang.String")) { 
				Method m = model.getClass().getMethod("get" + name);
				//调用getter方法获取属性值
				String value = (String) m.invoke(model); 
				if (value != null) {
					System.out.println("attribute value:" + value);
				}
			}
			if (type.equals("class java.lang.Integer")) {
				Method m = model.getClass().getMethod("get" + name);
				Integer value = (Integer) m.invoke(model);
				if (value != null) {
					System.out.println("attribute value:" + value);
				}
			}
			if (type.equals("class java.lang.Short")) {
				Method m = model.getClass().getMethod("get" + name);
				Short value = (Short) m.invoke(model);
				if (value != null) {
					System.out.println("attribute value:" + value);
				}
			}
			if (type.equals("class java.lang.Double")) {
				Method m = model.getClass().getMethod("get" + name);
				Double value = (Double) m.invoke(model);
				if (value != null) {
					System.out.println("attribute value:" + value);
				}
			}
			if (type.equals("class java.lang.Boolean")) {
				Method m = model.getClass().getMethod("get" + name);
				Boolean value = (Boolean) m.invoke(model);
				if (value != null) {
					System.out.println("attribute value:" + value);
				}
			}
			if (type.equals("class java.util.Date")) {
				Method m = model.getClass().getMethod("get" + name);
				Date value = (Date) m.invoke(model);
				if (value != null) {
					System.out.println("attribute value:" + value.toLocaleString());
				}
			}
		}
	}
}
Global site tag (gtag.js) - Google Analytics