草庐IT

35、Java 中的 Math 类、Random 随机数、UUID、格式化字符串或数字、字符串和数字的相互转换、高精度计算、BigDecimal、计算机中的浮点数都是近似值

JavaLearnerZGQ 2023-05-03 原文

文章目录

一、Math 类

(1) 简介

✏️ java.lang.Math 类提供了常见的数学计算功能
✏️ Math 类被 final 修饰(不能被继承)
✏️ Math 类不能被实例化

🍀 Math 类中都是 static 成员
🍀 Math 类不能被实例化,里面的非静态成员就毫无意义

(2) 属性

 // 自然对数函数的底数(常量)
 public static final double E = 2.7182818284590452354;
 // π(圆周率)
 public static final double PI = 3.14159265358979323846;


刘徽开创了探索圆周率的精确方法。

祖冲之刘徽开创的探索圆周率的精确方法的基础上,首次将圆周率精算到小数点后第七位,即在3.14159263.1415927之间。

(3) 方法

① ceil 和 floor

public class TestDemo {
    public static void main(String[] args) {
        // 求绝对值: 666
        // 正数的绝对值是其本身, 负数的绝对值是其相反数
        System.out.println("求绝对值: " + Math.abs(-666));

        // 求两个数的最大值: 777
        System.out.println("求两个数的最大值: " + Math.max(666, 777));

        // 求两个数的最小值: 2.36
        System.out.println("求两个数的最小值: " + Math.min(3.14, 2.36));
    }
}

🍀 max 方法可以求 int、long、float、double 等类型的两个数的最大值
🍀 体现了 Java 中的方法的重载特性
🍀 重载:① 方法名相同,参数类型或数量不同;② 重载与返回值类型、参数名称无关
🍀 Math 类中有很多重载的方法


public class TestDemo {
    public static void main(String[] args) {
        double n1 = 3.14159;
        double n2 = -3.04159;

        // 向下取整: 3.0
        System.out.println("向下取整: " + Math.floor(n1));

        // 向上取整: 4.0
        System.out.println("向上取整: " + Math.ceil(n1));

        // 向下取整: -4.0
        System.out.println("向下取整: " + Math.floor(n2));

        // 向上取整: -3.0
        System.out.println("向上取整: " + Math.ceil(n2));
    }
}

🍀 floor(地板):向下取整(最接近操作数的整数,并且要比操作数
🍀 ceil(天花板):向上取整(最接近操作数的整数,并且要比操作数

public class TestDemo {
    public static void main(String[] args) {
        double n1 = 3.44159;
        double n2 = -3.54159;

        // 四舍五入: 3
        System.out.println("四舍五入: " + Math.round(n1));
        // 四舍五入: -4
        System.out.println("四舍五入: " + Math.round(n2));
    }
}

② Knowledge is power

🍀 弗朗西斯培根: 出生于英国伦敦,其父亲是伊丽莎白女王的掌玺大臣。
🍀 Knowledge is power. 来自于弗朗西斯培根
🍀 他在《培根随笔》中的文章 📗《论读书》写得非常非常好(下面看其片段)
🍀 英文版的读起来还是比较费劲,博主选择了个人觉得翻译得通俗易懂的(咬文嚼字的不要)

🌱 读书可以作为消遣,可以作为装饰,也可以增长才干
🌱 孤独寂寞时,阅读可以消遣;高谈阔论时,知识可供装饰;处世行事时,知识意味着才干
🌱 懂得事务因果的人是幸运的。有实际经验的人虽能够处理个别性的事务,但若要纵观整体,运筹全局,却唯有学识方能办到读书太慢的人驰惰,为装潢而读书是欺人,完全按照书本做事就是呆子
🌱💐 求知可以改进人性,而经验可以改进知识本身。人的天性犹如野生的花草,求知学习好比修剪移栽。学问虽能指引方向,但往往流于浅乏,必须依靠经验才能扎下根基。
🌱 狡诈者轻鄙学问,愚鲁者羡慕学问,聪明者则运用学问。 知识本身并没有告诉人怎么运用它,运用的智慧在于书本之外。这是技艺,不体验就学不到。
🌱 读书是为了认识事物原理。为挑剔辩驳去读书是无聊的,但也不可过于迷信书本。求知不是为了吹嘘炫耀,而是为了寻找真理,启迪智慧
🌱 书籍好比食物。有些只须浅尝,有些可以吞咽,只有少数需要仔细咀嚼,慢慢品味。所以,有的书只须读其中一部分,有的书只须知其梗概,而对于少数好书,则应当通读、细读、反复读。
🌱 有的书可以请人代读,然后看 TA 的笔记摘要即可。但这只应限于不太重要的议论和质量粗劣的书。否则一本书就将像已被蒸馏过的水,变得淡而无味了。


✏️ 书归正传,Knowledge is power. 中的 power 是力量或权力的意思,但在数学上也表示幂、次方

public class TestDemo {
    public static void main(String[] args) {
        // 2的3次方: 8.0
        System.out.println("2的3次方: " + Math.pow(2, 3));
    }
}

🍀 Math 类的 pow 方法用于求数的次方值,pow 就来自于power

③ sqrt

✏️ sqrtSquare Root 的简写,意思是:平方根

public class TestDemo {
    public static void main(String[] args) {
        // 计算平方根: 8.0
        System.out.println("计算平方根: " + Math.sqrt(64));
    }
}

④ sin、cos、角度转弧度

public class TestDemo {
    public static void main(String[] args) {
        double degree = 90; // 角度制
        // 角度转换为弧度
        double radian = Math.toRadians(degree);

        // 计算 sin、cos、tan 等三角函数的时候, 需要把角度转换为弧度
        // sin: 1.0
        System.out.println("sin: " + Math.sin(radian));
        // cos: 6.123233995736766E-17
        System.out.println("cos: " + Math.cos(radian));
        // tan: 1.633123935319537E16
        System.out.println("tan: " + Math.tan(radian));
    }
}

(4) Math.random() 和 Random 类

✏️ Math.random()可以生成[0.0, 1.0)范围的随机数【包括0,不包括1.0

✏️ java.util.Random可以更方便地生成各种随机数(boolean 类型、int 类型、double 类型、long 类型 …) 👍

public class TestDemo {
    public static void main(String[] args) {
        Random random = new Random();

        boolean randBool = random.nextBoolean();
        int randInt = random.nextInt();
        long randLong = random.nextLong();
        float randFloat = random.nextFloat();

        // randBool = false
        System.out.println("randBool = " + randBool);
        // randInt = 1742425555
        System.out.println("randInt = " + randInt);
        // randLong = -83656586469544965
        System.out.println("randLong = " + randLong);
        // randFloat = 0.106951594
        System.out.println("randFloat = " + randFloat);
    }
}

🍀 这几个方法生成的随机数是无法指定范围的
🍀 可通过下面的练习学习如何生成指定范围的随机数

① 生成 [0, 99] 范围的整数

public class Randoms {
    /**
     * (1) Math.random() 生成的是 [0.0, 1.0] 范围的随机数
     * (2) 乘以 100 之后就是 [0.0, 100.0) 的浮点数
     * (3) 强转为 int 类型后就是 [0, 99] 的整数
     */
    private static int createRandNum0To99() {
        return (int) (Math.random() * 100);
    }

    private static int createRandNum0To99_() {
        // 生成 [0, 100) 的随机整数
        // [0, 100) 其实就是 [0, 99]
        return new Random().nextInt(100);
    }
}

🍀 new Random().nextInt(n) 生成 [0, n) 范围的随机整数

② 生成 [10, 99] 范围的整数

public class Randoms {
    /**
     * (1) (int) (Math.random() * 90): 生成的是 [0, 89] 的随机整数
     * (2) 加上 10 后生成的就是 [10, 99] 的随机整数
     */
    private static int createRandNum10To99() {
        return (int) (Math.random() * 90) + 10;
    }
    
    private static int createRandNum10To99_() {
        Random random = new Random();
        return 10 + random.nextInt(90);
    }
}

③ 生成四位大写字母随机字符串

public class RandStrFour {
    public static void main(String[] args) {
        char aLetter = 'A';
        for (int i = 0; i < 4; i++) {
            Random random = new Random();
            char i1 = (char) random.nextInt(25);
            System.out.print((char) (aLetter + i1));
        }
    }
}

二、UUID

✏️ UUID(Universally Unique Identifier):通用唯一标识符

✏️ UUID 的作用:让分布式系统中的所有元素都能有唯一的标识符,而不需要通过中央控制端来做标识符的指定

✏️ 可以使用java.util.UUID类的 randomUUID 方法生成一个32位的16进制数的随机字符串,可用该字符串作为 UUID

public class UUIDTest {
    public static void main(String[] args) {
        // 87fe7457-abb9-4de7-bb9b-9fe34fda11dd
        // 绝对是随机且唯一的
        System.out.println(UUID.randomUUID());
    }
}

三、格式化字符串或数字

(1) 格式化字符串

🍀 这东西蛮好用的

✏️ 可用 System.out.printfSystem.out.format 输出格式化的字符串

public class TestDemo {
    public static void main(String[] args) { 
        String sentence = "%s, %s和%s去%s结婚了, 当时他们都才%d岁";

        // 2022年08月09日, 莫松和陆昊去美国白宫结婚了, 当时他们都才20岁
        System.out.printf(sentence, "2022年08月09日", "莫松", "陆昊", "美国白宫", 20);
        System.out.println();
        // 2022年08月08日, 杨嘉立和叶霆去美国大使馆结婚了, 当时他们都才12岁
        System.out.format(sentence, "2022年08月08日", "杨嘉立", "叶霆", "美国大使馆", 12);
    }
}

✏️ 也可以使用String类的 format 方法创建格式化的字符串

public class TestDemo {
    public static void main(String[] args) {
        String s = String.format("%s, 英国女王的%s, %d年成为英国皇室的第一大臣", "庆医", "干儿子", 2022);
        // 庆医, 英国女王的干儿子, 2022年成为英国皇室的第一大臣
        System.out.println(s);
    }
}

🍀 这里面使用到了可变参数

占位符号作用
%d十进制整数
%f浮点数
%s字符串
%n换行

(2) 格式化数字(DecimalFormat)

🍀 使用 java.text.DecimalFormat 可以更好地控制前0后0前缀后缀分组分隔符十进制分隔符等。

public class TestDemo {
   public static void main(String[] args) {
       double doubleVal1 = 520360.123;
       double doubleVal2 = 123.78;
       double doubleVal3 = 12345.78;

       // 520,360.123
       System.out.println(customFormat("###,###.###", doubleVal1));

       // 520360.12
       System.out.println(customFormat("###.##", doubleVal1));

       // 000123.780
       System.out.println(customFormat("000000.000", doubleVal2));

       // $12,345.78
       System.out.println(customFormat("$###,###.###", doubleVal3));
   }

   /**
    * 把 double 类型的值转换为指定的字符串格式
    *
    * @param pattern 转换格式
    * @param value   待转换的数
    * @return 转换后的字符串
    */
   private static String customFormat(String pattern, double value) {
       DecimalFormat df = new DecimalFormat(pattern);
       return df.format(value);
   }
}

(3) 字符串转数字

🍀 包装类型的valueOf方法可以传入基本类型字符串, 然后将其转换为包装类型


🍀 包装类型的parsexxx方法可以把一个字符串转化为对应数字的基本类型

✏️ 必须保证待转换的字符串是可以被转换为相应数字的,否则会抛数字转换异常NumberFormatException

public class TestDemo {
    public static void main(String[] args) {
        String intStr = "520";
        String doubleStr = "66.88";

        Integer i1 = Integer.valueOf(intStr);
        Double d1 = Double.valueOf(doubleStr);
        // 520
        System.out.println(i1);
        // 66.88
        System.out.println(d1);

        int i2 = Integer.parseInt(intStr);
        double d2 = Double.parseDouble(doubleStr);
        // 520
        System.out.println(i2);
        // 66.88
        System.out.println(d2);
    }
}

(4) 数字转字符串

🍀 字符串的valueOf方法可把数字、对象或 char 数字转换为字符串

🍀 包装类的toString 方法可把其包装的基本类型转换为字符串

public class TestDemo {
    public static void main(String[] args) {
        int i = 1;
        double d = 66.666;
        boolean b = true;

        String iStr0 = i + "";
        String dStr0 = d + "";
        String bStr0 = b + "";

        // 1
        System.out.println(iStr0);
        // 66.666
        System.out.println(dStr0);
        // true
        System.out.println(bStr0);

        String iStr = String.valueOf(i);
        String dStr = String.valueOf(d);
        String bStr = String.valueOf(b);

        String iString = Integer.toString(i);
        String dString = Double.toString(d);
        String bString = Boolean.toString(b);

        // true
        System.out.println(iStr.equals(iString));
        // true
        System.out.println(dStr.equals(dString));
        // true
        System.out.println(bStr.equals(bString));
    }
}

🍀 基本类型转换为字符串可通过拼接一个空串来简单实现

四、高精度计算

(1) 计算机中浮点数都是近似值

💐 floatdouble 存储的只是小数的近视值,并非精确值,因此不适合用来做高精度计算

💐 小数转换为二进制可能是无穷的(如:0.7)

💐 计算机保留的仅仅是 0.7 的二进制数的一部分(所以浮点数在计算机中肯定是近似值)

public class TestDemo {
    public static void main(String[] args) {
        double d1 = 0.7;
        double d2 = 0.7;
        // 0.48999999999999994
        System.out.println(d1 * d2);
    }
}

(2) BigDecimal

💐 java.math.BigDecimal 类可专门用来做高精度计算
💐 通过数字字符串创建 BigDecimal 对象
💐 通过 BigDecimal 内的方法计算加、减、乘和除

public class TestDemo {
    public static void main(String[] args) {
        double d1 = 0.7;
        double d2 = 0.7;

        BigDecimal n1 = new BigDecimal(d1 + "");
        BigDecimal n2 = new BigDecimal(String.valueOf(d2));

        // 1.4
        System.out.println(n1.add(n2));
        // 0.0
        System.out.println(n1.subtract(n2));
        // 0.49
        System.out.println(n1.multiply(n2));
        // 1
        System.out.println(n1.divide(n2));
    }
}

结束, 如有错误请不吝赐教

有关35、Java 中的 Math 类、Random 随机数、UUID、格式化字符串或数字、字符串和数字的相互转换、高精度计算、BigDecimal、计算机中的浮点数都是近似值的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. Ruby 解析字符串 - 2

    我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

  3. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  4. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  5. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  6. ruby-on-rails - unicode 字符串的长度 - 2

    在我的Rails(2.3,Ruby1.8.7)应用程序中,我需要将字符串截断到一定长度。该字符串是unicode,在控制台中运行测试时,例如'א'.length,我意识到返回了双倍长度。我想要一个与编码无关的长度,以便对unicode字符串或latin1编码字符串进行相同的截断。我已经了解了Ruby的大部分unicode资料,但仍然有些一头雾水。应该如何解决这个问题? 最佳答案 Rails有一个返回多字节字符的mb_chars方法。试试unicode_string.mb_chars.slice(0,50)

  7. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  8. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  9. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  10. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

随机推荐