JAVA表达式之谜

一、奇数性

 

下面方法的目的是确定一个数是否为奇数

 

public static boolean isOdd(int i){ 

    return i % 2 == 1; 

} 

分析:这是Java对取余操作符(%)的定义所产生的,上述方法对于所有的负奇数判断都会失败,在任何负整数上调用该方法都会返回false,不管该负整数是奇数还是偶数。因为 -1 % 2 的结果是 -1,有符号。

建议:无论你何时使用到了取余操作符,都要考虑到操作数和结果的符号。

解决:

所以上述代码改正如下:

public static boolean isOdd(int i){ 

    return i % 2 != 0; 

}

如果是在一个强调性能的环境中,使用位操作符 & 替代取余操作符会更好

public static boolean isOdd3(int i){ 

    return (i & 1) != 0; 

} 

二、长整数

 

    final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000;

    final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;

    System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);

 

输出结果为:5

分析:所有的计算因子都是int类型的,所以在连乘的时候,两个int类型的数相乘最终得到的还是int类型的,24*60*60*1000*1000这个计算在乘以最后一个1000的时候结果超出了2147483647(int能表示的最大值)发生了溢出,虽然计算的结果放入Long中,但是这个计算是完全以int类型来计算的。

建议:当操作很大的数字时,要堤防溢出

解决:强制表达式中的所有后缀计算用Long运算来完成

    final long MICROS_PER_DAY = 24L * 60 * 60 * 1000 * 1000;

    final long MILLIS_PER_DAY = 24L* 60 * 60 * 1000;

    System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);

注:因为连乘是从左到右计算的,所以强制转换应该从第一个参与计算的数据开始

下列转换方式是错误的

    final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000L;

    final long MILLIS_PER_DAY = 24* 60 * 60 * 1000L;

    System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);

 

三、找零时刻

    System.out.println(2.00 - 1.10);

输出结果:0.8999999999999999

分析:并不是所有的小数都可以用二进制浮点数精确表示

建议:在需要精确答案的地方,要避免使用float和double。对于货币计算,要使用int、long、BigDecimal。一定要用BigDecimal(String)构造器,而千万不要用BigDecimal(double)。后一个构造器将用它的参数的精确值来创建一个实例。

解决:

1、JDK1.5或更新的版本,可以使用printf方法

    System.out.printf("%.2f",2.0-1.1); 

2、 使用BigDecimal类

    System.out.println(new BigDecimal("2.00").subtract(new BigDecimal("1.10")));

 

四、多重转型

 

    System.out.println((int) (char) (byte) -1);//65535

        

    System.out.println(0xffffffff);//-1

    byte b= -1; 

    System.out.println((int)(char) b ); //65535

    System.out.println((int)(char)(b & 0xff));//255

    System.out.println((byte)128);//-128

分析如果最初的数值类型是有符号的,就执行符号扩展。如果是char,那么不管它将要被转换成什么类型,都执行零扩展。

一、Java中如何编码负数?

    Java采用”2的补码“(Two's Complement)编码负数,它是一种数值的编码方法,要分二步完成:

    第一步,每一个二进制位都取相反值,0变成1,1变成0。比如,+8的二进制编码是00001000,取反后就是11110111。

    第二步,将上一步得到的值加1。11110111就变成11111000。所以,00001000的2的补码就是11111000。也就是说,-8在计算机(8位机)中就是用11111000表示。

二、什么是符号扩展(Sign Extension)?

    符号扩展(Sign Extension)用于在数值类型转换时扩展二进制位的长度,以保证转换后的数值和原数值的符号(正或负)和大小相同,一般用于较窄的类型(如byte)向较宽的类型(如int)转换。扩展二进制位长度指的是,在原数值的二进制位左边补齐若干个符号位(0表示正,1表示负)。

    举例来说,如果用6个bit表示十进制数10,二进制码为"00 1010",如果将它进行符号扩展为16bits长度,结果是"0000 0000 0000 1010",即在左边补上10个0(因为10是正数,符号为0),符号扩展前后数值的大小和符号都保持不变;如果用10bits表示十进制数-15,使用“2的补码”编码后,二进制码为"11 1111 0001",如果将它进行符号扩展为16bits,结果是"1111 1111 1111 0001",即在左边补上6个1(因为-15是负数,符号为1),符号扩展前后数值的大小和符号都保持不变。

三、Java类型转换规则

1. Java中整型字面量   

 Java中int型字面量的书写方式有以下几种:

    - 十进制方式,直接书写十进制数字

    - 八进制方式,格式以0打头,例如012表示十进制10

    - 十六进制方式,格式为0x打头,例如0xff表示十进制255

 需要注意的是,在Java中012和0xff返回的都是int型数据,即长度是32位。

2. Java的数值类型转换规则

    这个规则是《Java解惑》总结的:如果最初的数值类型是有符号的,那么就执行符号扩展;如果是char类型,那么不管它要被转换成什么类型,都执行零扩展。还有另外一条规则也需要记住,如果目标类型的长度小于源类型的长度,则直接截取目标类型的长度。例如将int型转换成byte型,直接截取int型的右边8位。

四、解析“多重转型”问题

    连续三次类型转换的表达式如下:

(int)(char)(byte)-1

1. int(32位) -> byte(8位)

    -1是int型的字面量,根据“2的补码”编码规则,编码结果为0xffffffff,即32位全部置1.转换成byte类型时,直接截取最后8位,所以byte结果为0xff,对应的十进制值是-1.

2. byte(8位) -> char(16位)

    由于byte是有符号类型,所以在转换成char型(16位)时需要进行符号扩展,即在0xff左边连续补上8个1(1是0xff的符号位),结果是0xffff。由于char是无符号类型,所以0xffff表示的十进制数是65535。

3. char(16位) -> int(32位)

    由于char是无符号类型,转换成int型时进行零扩展,即在0xffff左边连续补上16个0,结果是0x0000ffff,对应的十进制数是65535。

总结:实际上在数值类型转换时,只有当遇到负数时才会出现问题,根本原因就是Java中的负数不是采用直观的方式进行编码,而是采用“2的补码”方式,这样的好处是加法和减法操作可以同时使用加法电路完成,但是在开发时却会遇到很多奇怪的问题,例如(byte)128的结果是-128,即一个大的正数,截断后却变成了负数。

 

 

 

 

 

 

 

在使用Python来安装geopandas包时,由于geopandas依赖于几个其他的Python库(如GDAL, Fiona, Pyproj, Shapely等),因此安装过程可能需要一些额外的步骤。以下是一个基本的安装指南,适用于大多数用户: 使用pip安装 确保Python和pip已安装: 首先,确保你的计算机上已安装了Python和pip。pip是Python的包管理工具,用于安装和管理Python包。 安装依赖库: 由于geopandas依赖于GDAL, Fiona, Pyproj, Shapely等库,你可能需要先安装这些库。通常,你可以通过pip直接安装这些库,但有时候可能需要从其他源下载预编译的二进制包(wheel文件),特别是GDAL和Fiona,因为它们可能包含一些系统级的依赖。 bash pip install GDAL Fiona Pyproj Shapely 注意:在某些系统上,直接使用pip安装GDAL和Fiona可能会遇到问题,因为它们需要编译一些C/C++代码。如果遇到问题,你可以考虑使用conda(一个Python包、依赖和环境管理器)来安装这些库,或者从Unofficial Windows Binaries for Python Extension Packages这样的网站下载预编译的wheel文件。 安装geopandas: 在安装了所有依赖库之后,你可以使用pip来安装geopandas。 bash pip install geopandas 使用conda安装 如果你正在使用conda作为你的Python包管理器,那么安装geopandas和它的依赖可能会更简单一些。 创建一个新的conda环境(可选,但推荐): bash conda create -n geoenv python=3.x anaconda conda activate geoenv 其中3.x是你希望使用的Python版本。 安装geopandas: 使用conda-forge频道来安装geopandas,因为它提供了许多地理空间相关的包。 bash conda install -c conda-forge geopandas 这条命令会自动安装geopandas及其所有依赖。 注意事项 如果你在安装过程中遇到任何问题,比如编译错误或依赖问题,请检查你的Python版本和pip/conda的版本是否是最新的,或者尝试在不同的环境中安装。 某些库(如GDAL)可能需要额外的系统级依赖,如地理空间库(如PROJ和GEOS)。这些依赖可能需要单独安装,具体取决于你的操作系统。 如果你在Windows上遇到问题,并且pip安装失败,尝试从Unofficial Windows Binaries for Python Extension Packages网站下载相应的wheel文件,并使用pip进行安装。 脚本示例 虽然你的问题主要是关于如何安装geopandas,但如果你想要一个Python脚本来重命名文件夹下的文件,在原始名字前面加上字符串"geopandas",以下是一个简单的示例: python import os # 指定文件夹路径 folder_path = 'path/to/your/folder' # 遍历文件夹中的文件 for filename in os.listdir(folder_path): # 构造原始文件路径 old_file_path = os.path.join(folder_path, filename) # 构造新文件名 new_filename = 'geopandas_' + filename # 构造新文件路径 new_file_path = os.path.join(folder_path, new_filename) # 重命名文件 os.rename(old_file_path, new_file_path) print(f'Renamed "{filename}" to "{new_filename}"') 请确保将'path/to/your/folder'替换为你想要重命名文件的实际文件夹路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值