Java精确计算问题
关键字strictfp是strict float point的缩写,指的是精确浮点,它是用来确保浮点数运算的准确性。
- JVM在执行浮点数运算时,如果没有指定strictfp关键字,此时计算结果可能会不精确,而且计算 结果在不同平台或厂商的虚拟机上会有不同的结果,导致意想不到的错误。而一旦使用了strictfp 来声明一个类、接口或者方法,那么在所声明的范围内,Java编译器以及运行环境会完全依照IEEE二进制浮点数算术标准来执行,在这个关键字声明的范围内所有浮点数的计算都是精确的。
需要注意的是,当一个类被strictfp修饰时,所有方法都会自动被strictfp修饰。因此,strictfp可以保证 浮点数运算的精确性,而且在不同的硬件平台会有一致的运行结果。但是精确计算事实上还是没有得到 保障,这是受到存储方式的限制。需要精确计算还是以来BigDecimal实现的。
常见数学计算
Java的Math类中包含了用于执行基本数学运算的属性和方法,如初等指数、对数、平方根和三角函数。
Math的方法都被定义为static 形式,通过Math类可以在主函数中直接调用。
- Math.sqrt()计算平方根
int k=16; //如果不能执行计算,则返回NaN
double res=Math.sqrt(k);
System.out.println(res);
- Math.pow(a, b)计算a的b次方
- Math.max(a,b)计算最大值
- Math.min(a,b)计算最小值
- Math.abs()求绝对值
- Math.ceil天花板的意思,就是返回大的值;floor地板的意思,就是返回小的值;round 四舍五入,float时返回int值,double时返回long值
double d1=-1234.567;
System.out.println(Math.ceil(d1));//-1234.0
System.out.println(Math.floor(d1));//-1235.0
System.out.println(Math.round(d1)); //-1235 容易出错的位置
d1=1234.567;
System.out.println(Math.ceil(d1)); //1235.0
System.out.println(Math.floor(d1));//1234.0
System.out.println(Math.round(d1)); //1235
random 取得一个大于或者等
字符类型 char
Java中存放字符采用的是Unicode编码字符集,2B,0-65535
- 字符类型的变量可以当作整数使用
- char c='a'; 注意:这里使用的是单引号,不是双引号,单引号中只能包含一个字符
- 需要记忆: '0' < 'A' <'a'
- Java也提供转义字符,以反斜杠(\)开头,将其后的字符转变为另外的含义于0.0小于不等于1.0的随机数
\ddd 1到3位8进制数所表示的字符(ddd) 例如'\110'实际就是字符H
\uxxxx 1到4位16进制数所表示的字符(xxxx),例如'\u9110'表示字符'鄐'
\’ 单引号字符,例如'\''
\" 双引号字符,例如'"'实际上是可以的,但是这样写可读性非常差,所以建议使用'\"'
\\ 反斜杠字符
基本使用
char c='h';
System.out.println((int)c); //获取'h'字符对应的unicode编码值 104 //GB2312 System.out.println(c); // c='ab' 语法报错,因为只能对应一个字符 //引入转移字符
c='\'';
c='\110';
System.out.println(c);//H
System.out.println((int)c);//72
c='\u0050';
System.out.println(c); //P
System.out.println((int)c);//80
布尔类型 boolean
boolean数据类型有两种文字值:true真和false假
在Java编程语言中boolean类型只允许使用boolean值,在整数类型和boolean类型之间无转换计算
- boolean类型被编译为int类型,等于是说JVM里占用字节和int完全一样,int是4个字节,于是
- boolean也是4字节
- 00000000 00000000 00000000 00000001:true
- 00000000 00000000 00000000 00000000:false
- boolean数组在Oracle的JVM中,编码为byte数组,每个boolean元素占用8位=1字节
- boolean[] fs = {true,false};
- {00000001,00000000}
基本数据类型转换
- 小转大自动转换
byte b1=123;
long k1=b1;
double kk=k1;
System.out.println(kk);
long kk = 123456L;
float ff=kk; //没有错误。float 4B long 8B
- 大转小需要强制转换
double dd=123.567;
long kk=(long)dd;
System.out.println(kk);
- 类型转换的语法:
int k=100;
char cc=(char)k; //强制类型转换:窄化操作
char k='d';
System.out.println((int)k);
boolean bb=true;
System.out.println((int)bb);//因为boolean类型和数值类型之间没有任何对应关系,所以这里的强转会报语法错误
- double
float f1=123.456;//语法报错,因为系统默认带小数点的数据为double类型,所以123.456是double类型的数据,而声明f1为float,所以这里需要进行数据类型转换或者进行特殊声明。如果浮点数转换为整数是直接截断小数部分。
float f1=(float)123.456;
float f1=123.456f; //数字末尾的f类似于数字末尾的L,用于进行数据类型的说明,f/F表示这是一个float类型的数据 d/D表示是一个double类型的数据
复合数据类型
复合数据类型包括:class类、interface接口、数组。
null 索引在运行时并没有对应的类型,但它可以被转换为任何类型(不能是简单类型)。
索引类型的默认值就是null
常量
常量就是指在程序执行期间其值不能发生变化的数据,常量是固定的。如整型常量123,实型常量
1.23,字符常量'A',布尔常量true等
需求:要求用户键盘输入一个整数的半径值,计算圆的面积和周长
Scanner sc = new Scanner(System.in);
System.out.println("请输入半径值:要求整数");
int r=0;//定义一个变量
r=sc.nextInt();//会等待用户输入整数值,如果不正确则会有红色报错信息
//计算园的面积
double res=3.14*r*r; //Math.pow(r, 2)
//计算圆的周长
double dd=3.14*2*r;
//输出计算结果
System.out.println("半径值为"+r+"的圆形面积为"+res);
如何接收键盘录入数据
java.util.Scanner类常用于控制台的输入,当需要使用控制台输入时即可调用这个类。
使用方法
- 首先需要构造一个Scanner类的对象,并且与标准输入流System.in关联 Scanner sc = new Scanner(System.in);
- 调用Scanner类对象sc的方法从输入流中获取你需要的输入
说明:
当创建了一个Scanner类对象之后,控制台会一直等待输入,直到敲回车键结束,把所输入的内容
传给对象sc,若要获取需要的内容,调用sc的方法即可
Scanner sc=new Scanner(System.in);
System.out.println("请输入园的半径值:"); //用于提示用户录入数据
int r=sc.nextInt(); //要求用户输入数据,否则阻塞等待用户输入
System.out.println("接受到的数据为"+r);
每次可以只输入一个数字,回车确认,例如123,只能被一个nextInt读取。
也可以输入一组数字,例如123 456 789,每个数字之间用空格(一个或多个空格)隔开,可被多
个nextInt()读取,空格及回车不会被读取。(注:输入数字中不能夹杂除数字、空格、回车之外的
其他字符,否则会报错)
如何在控制台输出数据
System.out.println(数据);
System.out.println("请输入园的半径值:");
int kk=100;
double res=3.14*kk*kk;
System.out.println("园的半径值为"+kk+",对应面积为"+res);