第一章节01 8大基本类型 和对强类型语言这几个字的真正理解

第一章节01

创建项目时的注意事项

  1. 一般都时建一个空的工程文件(project)然后再里面建Java模块便于管理,后再建class

  2. 设置工程结构

    image-20220901184831851

    将SDK和语言等级设置为同一等级,图中的都是8, 点击OK

image-20220901184707058

注释,标识符,关键字

注释

单行注释    //
多行注释    /*内容*/
文档注释	/**内容*/

标识符

都是由数字(19),字母(AZ,a~z),下划线(_),美元符号($)构成的,其中只有数字不能作为开头。

关键字

image-20220901195113612

数据类型

  • 强类型语言:变量先定义后使用,变量类型先定义在确定。java,c++
  • 弱类型语言:与上面相反。Js

Java的数据类型分为两类

image-20220901205143339

8大基本类型

整数型:byte

​ short

int

​ long 需要再后面加L,不然数据其实还是int

浮点型:float 需要再后面加F,不然数据还是double

double

字符型:char

布尔型:boolean 值是true和flase 不能和C语言一样用1,0赋值,也不能转换成其他类型

今日疑问

在数据类型的部分为什么 long,float要而外加L,F来表示自己的数据类型,一个默认是int比long短,一个默认是double比float长,为什么short和byte又不用再加后缀呢?

1.整型的转换问题

就比如 byte num1 = 100;这一行代码,在运算时100这个数字也是需要类型的,也是强类型语言的需要,默认的类型int。

运算的时候需要 !!左边不超出byte的范围(运算结束后的大小不超过byte),右边不超出int的范围!!

同理 long num2 =123;左边不能超过long的范围,右边不能超过int的范围不然无法运算,由下图可以看出是左边超过了int的范围导致无法计算。需要在后面加L才能进行运算

image-20220901213726740

image-20220901214330348

2.float和double互相转换的问题

float 是单精度浮点小数,而double 是双精度浮点小数,单精度型能精确到七位,而双精度能精确到15位。

如果要将Float和Double之间相互转型,java 提供了一下方法Float.doubleValue()和Double.floatValue()

查看JDK1.6中对其方法进行这样解释

Float.doubleValue()
public double doubleValue()
返回此 Float 对象的 double 值。
指定者:
类 Number 中的 doubleValue
返回:
此对象表示的 float 值被转换为 double 类型,并返回转换的结果。
Double.floatValue()
public float floatValue()
返回此 Double 对象的 float 值。
指定者:
类 Number 中的 floatValue
返回:
转换为 float 类型的由此对象所表示的 double 值
从以下版本开始:
JDK1.0
先从一个简单的例子进行说明一下:

public static void main(String[] args) {
Float f=new Float(14.1);
System.out.println(f.floatValue());
System.out.println(f.doubleValue());

	Double d = new Double(14.1);
	System.out.println(d.floatValue());
	System.out.println(d.doubleValue());
}

输出的结果是:
14.1
14.100000381469727
14.1
14.1

这时,可以看到Float.doubleValue()时,数字是不准确的,应该是14.1,而结果14.10000381469727,这就是单精度转双精度的时候,双精度会对单精度进行补位。导致出现偏差。

我这时的解决办法是这样的

Float f=new Float(14.1);
System.out.println(f.floatValue());
System.out.println(f.doubleValue());
System.out.println(Double.parseDouble(f.floatValue()+""));
输出的结果
14.1
14.100000381469727
14.1

再看下一个例子

public static void main(String[] args) {
	Float f=new Float(14.111111111111111111111111);
	System.out.println(f.floatValue());
	System.out.println(f.doubleValue());
	
	Double d = new Double(14.111111111111111111111111);
	System.out.println(d.floatValue());
	System.out.println(d.doubleValue());
}

输出结果:
14.111111
14.11111068725586
14.111111
14.11111111111111

这时,由于小数点后面的位数过长,Float单精度和Double双精度都进行一次截位后进行计算,这时,Float.doubleValue()仍然出现补位问题,但是这次补位已经将原有数据给破坏掉了。
为了减少误差,将Float的数据转换成double数据时,还是采取上一个操作办法

System.out.println(Double.parseDouble(f.floatValue()+""));
输出的结果是
14.111111
再看下面的例子

public static void main(String[] args) {
	Float f=new Float(14.6666666666666666666666666666666666666);
	System.out.println(f.floatValue());
	System.out.println(f.doubleValue());
	
	System.out.println(Double.parseDouble(f.floatValue()+""));
	
	Double d = new Double(14.6666666666666666666666666666666666666);
	System.out.println(d.floatValue());
	System.out.println(d.doubleValue());
}

输出的结果是
14.666667
14.666666984558105
14.666667
14.666667
14.666666666666666

这时会发现当给出的数据超出单精度的位数时,会截取,截取后的数字剩下的第一位大于5时,必然进位(即最后一位+1),小于5时,必然不进位(即最后一位不变)。
而截取后的数字剩下的第一位等于5时,有时会进位,有时会不进位。(查看源码,未找出原因)

双精度在此数值时未进位

再看下面的例子
public static void main(String[] args) {
Float f=new Float(14.777777777777777777777777);
System.out.println(f.floatValue());
System.out.println(f.doubleValue());

	System.out.println(Double.parseDouble(f.floatValue()+""));
	
	Double d = new Double(14.77777777777777777777777777777);
	System.out.println(d.floatValue());
	System.out.println(d.doubleValue());
}

这时的结果
14.777778
14.777777671813965
14.777778
14.777778
14.777777777777779

所以在大量数据的测试下,发现不管是单精度还是双精度准确的进位是无法确定的。

总结

在单精度转双精度的时候未防止补位问题采用

Double.parseDouble(f.floatValue()+"")
以保留单精度数据的准确性
而在双精度转单精度的时候,未发现错误的数据。基本可以和单精度是一样的。

终于写完了。。。。此文章主要是写给新手们看的。。。如有更好的解决办法可以直接评论。。。。。以便大家学习。。。。。

3.特别需要注意的是两个浮点数的算术运算

直接使用 +,-,*,%运算符的问题

    public class Test{
        public static void main(String args[]){
        System.out.println(0.05+0.01);
        System.out.println(1.0-0.42);
        System.out.println(4.015*100);
        System.out.println(123.3/100);
        }
    }



    结果:
    0.060000000000000005
    0.5800000000000001
    401.49999999999994
    1.2329999999999999

原因:

​ 首先得从计算机本身去讨论这个问题。我们知道,计算机并不能识别除了二进制数据以外的任何数据。无论我们使用何种编程语言,在何种编译环境下工作,都要先 把源程序翻译成二进制的机器码后才能被计算机识别。以上面提到的情况为例,我们源程序里的2.4是十进制的,计算机不能直接识别,要先编译成二进制。但问 题来了,2.4的二进制表示并非是精确的2.4,反而最为接近的二进制表示是2.3999999999999999。原因在于浮点数由两部分组成:指数和尾数,这点如果知道怎样进行浮点数的二进制与十进制转换,应该是不难理解的。如果在这个转换的过程中,浮点数参与了计算,那么转换的过程就会变得不可预 知,并且变得不可逆。我们有理由相信,就是在这个过程中,发生了精度的丢失。而至于为什么有些浮点计算会得到准确的结果,应该也是碰巧那个计算的二进制与 十进制之间能够准确转换。而当输出单个浮点型数据的时候,可以正确输出,如

double d = 2.4;
System.out.println(d);

​ 输出的是2.4,而不是2.3999999999999999。也就是说,不进行浮点计算的时候,在十进制里浮点数能正确显示。这更印证了我以上的想法,即如果浮点数参与了计算,那么浮点数二进制与十进制间的转换过程就会变得不可预知,并且变得不可逆。

​ 事实上,浮点数并不适合用于精确计算,而适合进行科学计算。这里有一个小知识:既然float和double型用来表示带有小数点的数,那为什么我们不称 它们为“小数”或者“实数”,要叫浮点数呢?因为这些数都以科学计数法的形式存储。当一个数如50.534,转换成科学计数法的形式为5.053e1,它 的小数点移动到了一个新的位置(即浮动了)。可见,浮点数本来就是用于科学计算的,用来进行精确计算实在太不合适了。

总结

只要是运算每一个运算数都需要一个类型,即使是 a=123 中的123也一样。

double和float互相转换可能会发生奇奇怪怪的错误,所以java中将他们输入时区分开

浮点数很可能没有办法精确的表达一个数字(0.1,0.2,0.3,0.4),会出现误差

posted @ 2022-09-01 22:39  A31  阅读(16)  评论(0编辑  收藏  举报