15.8 Math数学计算

本文介绍了Java编程中如何使用Math类进行数学计算,包括四舍五入、对数、乘方等操作。还展示了自定义四舍五入工具类的实现。此外,讲解了Random类生成随机数的方法,以及如何实现36选7的随机数选择。接着,探讨了大数字处理类BigInteger和BigDecimal的使用,包括四则运算和四舍五入。最后,提到了Date日期处理类和SimpleDateFormat日期格式化,用于获取和格式化日期时间。

程序开发的本质就是数据处理,Java提供有java.lang.Math类来帮助开发者进行常规的数学计算处理,例如,四舍五入、三角函数、乘方处理等。

范例:使用Math类进行数学计算

package cn.kuiba.util;

public  class Main {
    public static void main(String[] args) throws Exception {
        System.out.println(Math.abs(-10.1));                    //绝对值
        System.out.println(Math.max(10.2,20.3));                //获取最大值
        System.out.println(Math.log(5));                        //对数
        System.out.println(Math.round(15.1));                   //四舍五入
        System.out.println(Math.round(-15.5));
        System.out.println(Math.round(-15.51));
        System.out.println(Math.pow(10.2,20.2));                //乘方
    }
}


程序执行结果:
10.1
20.3
1.6094379124341003
15
-15
-16
2.364413713591828E20

范例:自定义四舍五入工具类

package cn.kuiba.util;
class MathUtil{
    private MathUtil(){};   //构造方法私有化

    /**
     * 进行准确位数的四舍五入处理操作
     * @param num 要进行四舍五入计算的数字
     * @param scale 保留的小数位
     * @return  四舍五入处理后的结果
     */
    public static double round(double num,int scale){
        return Math.round(num*Math.pow(10.0,scale))/Math.pow(10.0,scale);
    }
}
public  class Main {
    public static void main(String[] args) throws Exception {
        System.out.println(MathUtil.round(7.45124789023480234890,3));
    }
}


程序执行结果:
7.451

9. Random随机数

        java.util.Random类的主要功能是可以进行随机数的生成,开发者只需要为其设置一个随机数的范围边界就可以随机生成不大于此边界的正整数,生成方法如下。

随机生成正整数:public int nextInt(int bound)

范例:随机生成正整数

package cn.kuiba.util;

import java.util.Random;
public  class Main {
    public static void main(String[] args) throws Exception {
        Random random=new Random();
        for (int x=0;x<10;x++){
            System.out.println(random.nextInt(100)+"、");
        }
    }
}



程序执行结果:
46、43、78、97、86、97、64、17、47、12、

        随机生成了10个不大于100的正整数,并且也会有可能生成重复数字。

范例:实现36选7

       从1~36个数字中,随机抽取7个数字内容,并且这7个数字内容不能为0,也不能重复。

package cn.kuiba.util;
import java.util.Random;
public  class Main {
    public static void main(String[] args) throws Exception {
        int data[]=new int[7];                                     //开辟7个大小的空间
        Random random=new Random();
        int foot=0;                                                //操作data脚标
        while (foot<7){                                            //选择7个数字
            int num=random.nextInt(37);                     //生成1个数字
            if (isUse(num,data)){                                  //该数字现在可以使用
                data[foot++]=num;                                  //保存数据
            }
        }
        java.util.Arrays.sort(data);                               //数组排序
        printArray(data);                                          //输出数组内容
    }

    /**
     * 将接收到的整形数组内容进行输出
     * @param temp  数组临时变量
     */
    public static void printArray(int temp[]){
        for (int x=0;x<temp.length;x++){                          //for循环输出
            System.out.print(temp[x]+"、");                     //下标获取元素内容
        }
    }
    /**
     * 判断传入的数字是否为0以及是否在数组中存在 
     * @param num 要判断的数字
     * @param temp 已经存在的数据
     * @return 如果该数字不是0并且可以使用返回true,否则返回false
     */
    public static boolean isUse(int num,int temp[]){
        if (num==0){                                            //生成数字为0表示错误
            return false;
        }
        for (int x=0;x<temp.length;x++){
            if (num==temp[x]){                                  //生成数字已存在表示错误
                return false;
            }
        }
        return true;
    }
}



程序执行结果:
1、2、7、9、22、25、36、

        本程序为了防止保存错误的随机数,所以定义了一个isUse()方法进行0和重复内容的判断。由于Random类生成的随机数没有顺序,所以利用了Array.sort()实现了数组排序。

10. 大数字处理类

        当一个数学非常大的时候,是无法使用基本数据类型接收的。在java.math包中提供了大数字的操作类:BigInteger(整数)、BigDecimal(浮点数),这两类都是Number子类。继承结构如图,常用方法如表。

 

 

 范例:使用BigInteger实现四则运算

package cn.kuiba.util;
import java.math.BigInteger;
public  class Main {
    public static void main(String[] args) throws Exception {
        BigInteger bigA=new BigInteger("6789321987");
        BigInteger bigB=new BigInteger("13972");
        System.out.println("加法操作:"+bigA.add(bigB));
        System.out.println("减法操作:"+bigA.subtract(bigB));
        System.out.println("乘法操作:"+bigA.multiply(bigB));
        System.out.println("除法操作:"+bigA.divide(bigB));
        BigInteger result[]=bigA.divideAndRemainder(bigB);
        System.out.println("商:"+result[0]+"、余数:"+result[1]);
    }
}


程序执行结果:
加法操作:6789335959
减法操作:6789308015
乘法操作:94860406802364
除法操作:485923
商:485923、余数:5831

范例:使用BigDecimal实现四舍五入

package cn.kuiba.util;
import java.math.BigDecimal;
import java.math.RoundingMode;
class MathUtil{
    private MathUtil(){}
    /**
     * 实现数据的四舍五入操作
     * @param num 要进行四舍五入操作的数字
     * @param scale 四舍五入保留的小数位数
     * @return  四舍五入处理后的结果
     */
    public static double round(double num,int scale){
        //数字除以1.0还是数字本身,divide()方法保留指定位数的小数,并设置进位模式为向上进位(HALF_UP)
        return new BigDecimal(num).divide(new BigDecimal(1.0),scale,RoundingMode.HALF_UP).doubleValue();
    }
}
public  class Main {
    public static void main(String[] args) throws Exception {
        System.out.println(MathUtil.round(19.6352,2));
    }
}


程序执行结果:
19.64

        本程序主要利用了BigDecimal类的divide()除法操作实现了准确的小数位保留,同时利用向上进位模式实现了四舍五入操作。

11. Date日期处理类

        Java中如果想要获得当前的日期时间可以通过java.util.Date类来实现,常用方法如下:

 范例:获取当前日期时间

package cn.kuiba.util;
import java.util.Date;
public  class Main {
    public static void main(String[] args) throws Exception {
        Date date=new Date();
        System.out.println(date);
    }
}


程序执行结果:
Wed May 11 17:44:19 CST 2022

范例:Date与long之间转换处理

package cn.kuiba.util;
import java.util.Date;
public  class Main {
    public static void main(String[] args) throws Exception {       //简化异常处理
        Date date=new Date();                                       //实例化Date类对象
        long current=date.getTime();                                //获得当前时间戳数字
        current+=864000*1000;                                       //10天的秒数
        System.out.println(new Date(current));                      //long转换为Date
    }
}



程序执行结果:
Sat May 21 17:46:24 CST 2022

        Date类对象保存时间戳是以毫秒的形式记录的,本程序获取了10天之后的日期。

提示:JDK1.8开始提供有java.time.LocalDateTime类,提供有java.time支持包,可直接进行日期时间操作。

package cn.kuiba.util;
import java.time.LocalDateTime;
public  class Main {
    public static void main(String[] args) throws Exception {
        LocalDateTime localDateTime=LocalDateTime.now();
        System.out.println(localDateTime);
    }
}


程序执行结果:
2022-05-11T17:51:17.005

可以方便的获取日期时间数据,而后也可以方便的进行日期时间的累加。

12. SimpleDateFormat日期格式化

        使用java.util.Date类可以获取当前日期,但是结果不方便阅读,那么考虑对结果进行格式化处理,通过java.text.SimpleDateFormat类完成。继承关系如图。

         常用方法如表。

         在日期格式化操作中必须设置有完整的日期转化模板,模板中通过特定的日期标记可以将一个日期格式中的日期数字提取出来。模板如表。

 范例:将日期格式化为字符串

package cn.kuiba.util;
import java.text.SimpleDateFormat;
import java.util.Date;
public  class Main {
    public static void main(String[] args) throws Exception {
        Date date=new Date();
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss.SSS");
        String str=sdf.format(date);
        System.out.println(str);
    }
}



程序执行结果:
2022-05-11  18:14:08.798

范例:将字符串转为Date对象

package cn.kuiba.util;
import java.text.SimpleDateFormat;
import java.util.Date;
public  class Main {
    public static void main(String[] args) throws Exception {
        String birthday="2001-01-14  12:46:05.542";
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        Date date=sdf.parse(birthday);
        System.out.println(date);
    }
}


程序执行结果:
Sun Jan 14 12:46:05 CST 2001

public class CoordinateConverter { // 珠三角优化参数(经多次测试调整) private static final double[] LON_PARAMS = {0.00352, 0.000121, -0.000132, 0.0000012, 0.0000018, -0.0000005}; private static final double[] LAT_PARAMS = {-0.00142, -0.000085, 0.000208, -0.0000008, -0.0000015, 0.0000004}; public static void main(String[] args) { double lonBd = 113.957096980672; double latBd = 22.5287839700245; double[] wgs84 = bd09ToWgs84(lonBd, latBd); System.out.printf("原始BD-09: (%.6f, %.6f)%n", lonBd, latBd); System.out.printf("转换结果: (%.6f, %.6f)%n", wgs84[0], wgs84[1]); System.out.printf("实际坐标: (113.945849, 22.525772)%n"); System.out.printf("误差: %.2f米%n", calculateDistance(wgs84[0], wgs84[1], 113.945849, 22.525772)); } public static double[] bd09ToWgs84(double lngBd, double latBd) { double[] gcj = bd09ToGcj02(lngBd, latBd); return gcj02ToWgs84Regional(gcj[0], gcj[1]); } private static double[] bd09ToGcj02(double lng, double lat) { double x = lng - 0.0065; double y = lat - 0.006; double z = Math.sqrt(x*x + y*y) - 0.00002 * Math.sin(y * Math.PI * 3000.0 / 180.0); double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * Math.PI * 3000.0 / 180.0); return new double[]{ z * Math.cos(theta), z * Math.sin(theta) }; } private static double[] gcj02ToWgs84Regional(double lng, double lat) { // 相对中心点坐标(珠三角中心) double dx = lng - 114.0; // 经度偏移量 double dy = lat - 22.5; // 纬度偏移量 // 经度偏移量计算(多项式回归) double deltaLon = LON_PARAMS[0] + LON_PARAMS[1] * dx + LON_PARAMS[2] * dy + LON_PARAMS[3] * dx * dx + LON_PARAMS[4] * dy * dy + LON_PARAMS[5] * dx * dy; // 纬度偏移量计算 double deltaLat = LAT_PARAMS[0] + LAT_PARAMS[1] * dx + LAT_PARAMS[2] * dy + LAT_PARAMS[3] * dx * dx + LAT_PARAMS[4] * dy * dy + LAT_PARAMS[5] * dx * dy; return new double[]{lng - deltaLon, lat - deltaLat}; } // 计算两点间距离(米) private static double calculateDistance(double lon1, double lat1, double lon2, double lat2) { double R = 6371000; // 地球半径 double dLat = Math.toRadians(lat2 - lat1); double dLon = Math.toRadians(lon2 - lon1); double a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.sin(dLon/2) * Math.sin(dLon/2); double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); return R * c; } }原始BD-09: (113.957097, 22.528784) 转换结果: (113.947047, 22.524489) 实际坐标: (113.945849, 22.525772) 误差: 188.37米 坐标在深圳,如何优化
最新发布
11-27
public class CoordinateConverter { private static final CRSFactory crsFactory = new CRSFactory(); private static final CoordinateTransformFactory ctFactory = new CoordinateTransformFactory(); public static double[] bd09ToWgs84(double lng, double lat) { try { CoordinateReferenceSystem bd09 = crsFactory.createFromName("EPSG:4610"); // BD-09 CoordinateReferenceSystem wgs84 = crsFactory.createFromName("EPSG:4326"); // WGS84 CoordinateTransform transform = ctFactory.createTransform(bd09, wgs84); ProjCoordinate result = new ProjCoordinate(); transform.transform(new ProjCoordinate(lng, lat), result); return new double[]{result.x, result.y}; } catch (Exception e) { // 回退算法 return gcj02ToWgs84Regional(lng, lat); } } // 带高程校正的转换模型 private static final double EARTH_RADIUS = 6378137; // WGS84椭球体半径 private static final double EE = 0.006693421622965943; // 偏心率平方 public static double[] gcj02ToWgs84Regional(double lng, double lat) { // 动态计算区域中心点(以深圳为中心) double centerLng = 113.883921; double centerLat = 22.51646; // 带高程的偏移量计算 double radLat = Math.toRadians(lat); double magic = Math.sin(radLat); magic = 1 - EE * magic * magic; double sqrtMagic = Math.sqrt(magic); // 改进的多项式参数(深圳区域) double dx = (lng - centerLng) * 111319.49 * Math.cos(radLat); double dy = (lat - centerLat) * 110946.30; double deltaLon = (20.0 * dx + 5.0 * dy + 0.1 * dx * dy) / (EARTH_RADIUS * sqrtMagic * Math.PI / 180); double deltaLat = (25.0 * dy - 3.0 * dx + 0.1 * dx * dx) / ((EARTH_RADIUS * (1 - EE)) / (magic * sqrtMagic) * Math.PI / 180); return new double[]{lng - deltaLon, lat - deltaLat}; } public static void main(String[] args) { double lonBd = 113.86627; double latBd = 22.516525; double[] wgs84 = bd09ToWgs84(lonBd, latBd); System.out.printf("原始BD-09: (%.6f, %.6f)%n", lonBd, latBd); System.out.printf("转换结果: (%.6f, %.6f)%n", wgs84[0], wgs84[1]); System.out.printf("实际坐标: (113.883921, 22.51646)%n"); System.out.printf("误差: %.2f米%n", calculateDistance(wgs84[0], wgs84[1], 113.883921, 22.51646)); } // 使用Vincenty公式(精度0.5mm) public static double calculateDistance(double lon1, double lat1, double lon2, double lat2) { double a = 6378137, b = 6356752.314245, f = 1/298.257223563; double L = Math.toRadians(lon2 - lon1); double U1 = Math.atan((1-f) * Math.tan(Math.toRadians(lat1))); double U2 = Math.atan((1-f) * Math.tan(Math.toRadians(lat2))); double sinU1 = Math.sin(U1), cosU1 = Math.cos(U1); double sinU2 = Math.sin(U2), cosU2 = Math.cos(U2); double lambda = L, lambdaP = 2*Math.PI; int iterLimit = 100; double cosSqAlpha, sinSigma, cosSigma, cos2SigmaM, sigma; do { double sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda); sinSigma = Math.sqrt((cosU2*sinLambda)*(cosU2*sinLambda) + (cosU1*sinU2 - sinU1*cosU2*cosLambda)*(cosU1*sinU2 - sinU1*cosU2*cosLambda)); if (sinSigma == 0) return 0; cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda; sigma = Math.atan2(sinSigma, cosSigma); double sinAlpha = cosU1*cosU2*sinLambda/sinSigma; cosSqAlpha = 1 - sinAlpha*sinAlpha; cos2SigmaM = (cosSqAlpha != 0) ? cosSigma - 2*sinU1*sinU2/cosSqAlpha : 0; double C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha)); lambdaP = lambda; lambda = L + (1-C)*f*sinAlpha* (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM))); } while (Math.abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0); if (iterLimit == 0) return Double.NaN; double uSq = cosSqAlpha * (a*a - b*b)/(b*b); double A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq))); double B = uSq/1024*(256+uSq*(-128+uSq*(74-47*uSq))); double deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)- B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM))); return b*A*(sigma - deltaSigma); } }原始BD-09: (113.866270, 22.516525) 转换结果: (113.866270, 22.516525) 实际坐标: (113.883921, 22.51646) 误差: 1816.02米 目前有一批深圳的坐标点,转化成WGS后误差较大。优化v
11-26
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值