Java浮点运算问题,为什么最后一个小数位总是会有误差?

F1ng 2016-05-31 10:53:25
package work;
import java.math.BigDecimal;
//工具类
public class DecimalCalculate {
/**
*
*
* 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精 确的浮点数运算,包括加减乘除和四舍五入。
*/

// 默认除法运算精度
private static final int DEF_DIV_SCALE = 10;

// 这个类不能实例化
private DecimalCalculate() {
}

/**
* 提供精确的加法运算。
*
* @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));
BigDecimal value = b1.add(b2);
return value.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_DIV_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();
}

/**
* 提供精确的类型转换(Float)
*
* @param v
* 需要被转换的数字
* @return 返回转换结果
*/
public static float convertsToFloat(double v) {
BigDecimal b = new BigDecimal(v);
return b.floatValue();
}

/**
* 提供精确的类型转换(Int)不进行四舍五入
*
* @param v
* 需要被转换的数字
* @return 返回转换结果
*/
public static int convertsToInt(double v) {
BigDecimal b = new BigDecimal(v);
return b.intValue();
}

/**
* 提供精确的类型转换(Long)
*
* @param v
* 需要被转换的数字
* @return 返回转换结果
*/
public static long convertsToLong(double v) {
BigDecimal b = new BigDecimal(v);
return b.longValue();
}

/**
* 返回两个数中大的一个值
*
* @param v1
* 需要被对比的第一个数
* @param v2
* 需要被对比的第二个数
* @return 返回两个数中大的一个值
*/
public static double returnMax(double v1, double v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.max(b2).doubleValue();
}

/**
* 返回两个数中小的一个值
*
* @param v1
* 需要被对比的第一个数
* @param v2
* 需要被对比的第二个数
* @return 返回两个数中小的一个值
*/
public static double returnMin(double v1, double v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.min(b2).doubleValue();
}

/**
* 精确对比两个数字
*
* @param v1
* 需要被对比的第一个数
* @param v2
* 需要被对比的第二个数
* @return 如果两个数一样则返回0,如果第一个数比第二个数大则返回1,反之返回-1
*/
public static int compareTo(double v1, double v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.compareTo(b2);
}

public static void main(String[] args) {
double info = 0.000;
double base = DecimalCalculate.div(5, 14, 3);
info += (-1) * base * Math.log(base);
System.out.println(info);
}

}

package work;
import java.util.Scanner;
import java.math.BigDecimal;

//圆类
public class Round {
static final float pai = 3.1415926f;
static float r;

//面积函数

public static float area(float temp){
float areNumber; //定义局部变量areNumber
float areNumber1; //定义局部变量areNumber1
areNumber1 = (float) DecimalCalculate.mul(temp, temp);
areNumber = (float) DecimalCalculate.mul(areNumber1, pai);
return areNumber;
}

// 周长函数
public static float primeter(float r){
float priNumber;
float priNumber1;
float changliang = 2.0f;
priNumber1 = (float) DecimalCalculate.mul(r, pai);
priNumber = (float) DecimalCalculate.mul(priNumber1,changliang);
return priNumber;

}

/**
* @param args
**/
public static void main(String[] args) {
// TODO Auto-generated method stub
float r_Primeter;
float r_Area;
System.out.print("请输入圆的周长:");
Scanner getInput = new Scanner(System.in);
r = getInput.nextFloat();
r_Primeter = primeter(r);
r_Area = area(r);
System.out.println();
System.out.println("该圆的周长为:" + r_Primeter);
System.out.print("该圆的面积为:" + r_Area);

}

}

运算结果:面积=13.854421
电脑计算器结果:面积=13.854423366
...全文
551 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
键圣 2016-06-06
  • 打赏
  • 举报
回复
首先说明一个问题float描述不了3.1415926这个数字的精度,转换成float就变成了3.1415925,再者double也不能精确描述
三张截图你理解下

huntor 2016-06-04
  • 打赏
  • 举报
回复
Java中浮点数遵循的是IEEE745标准,不等价于数学中的实数。
lyfuci 2016-06-04
  • 打赏
  • 举报
回复
浮点运算的自带属性吧,如果全程用BigDecimal可能没有。
Ordinary-1995 2016-06-02
  • 打赏
  • 举报
回复
有误差是正常的
  • 打赏
  • 举报
回复
Double.toString(v1)改为v1+"" new BigDecimal(参数尽量用字符串表示)
家里敷泥呀 2016-06-01
  • 打赏
  • 举报
回复
给你看个相关文档: Java中如何解决double和float精度不准的问题 - Yinan's Blog - 博客频道 - CSDN.NET http://blog.csdn.net/yinan9/article/details/17283081
小灰狼 2016-06-01
  • 打赏
  • 举报
回复
浮点四则运算,别说JAVA,就是C也可能存在误差 因二进制小数和十进制小数之间存在转换误差。比如一个十进制的小数,转换成二进制,可能就成了无限小数;反过来二进制的小数,转换为十进制,也成了无限小数
键圣 2016-06-01
  • 打赏
  • 举报
回复
把你的float改成double试试

62,628

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧