java学习笔记(持续更新中...)

news2024/10/7 6:38:45

Java 中的基本数据类型主要包括以下7种:

  1. byte:字节型,占用 1 字节,范围-128 到 127。
  2. char:字符型,占用 2 字节,范围 0 到 65535。
  3. short:短整型,占用 2 字节,范围-32768 到 32767。
  4. int:整型,占用 4 字节,范围-2147483648 到 2147483647。
  5. long:长整型,占用 8 字节,范围-9223372036854775808 到 9223372036854775807。
  6. float:单精度浮点型,占用 4 字节,有效位可以达到 6-7 位。精确到小数点后 6~7 位。
  7. double:双精度浮点型,占用 8 字节,有效位可以达到 15 位。精确到小数点后 15~16 位。

这些类型在内存中的占用大小是固定的,但是它们可以存储的值的大小或者精度是不同的。例如,byte、short、int、long 类型可以存储整数,但是它们存储的最大值和最小值是不同的;float 和 double 可以存储浮点数,但是它们的精度(小数点后几位)是不同的。

按照精度从大到小排列Java中这些基本数据类型,主要针对的是这些类型所能表示的数值范围或精确度,我们按照数值范围和精确度来排序:

  1. double:双精度浮点型,精度最高,可以表示的数非常大或非常小,精确到小数点后15~16位。
  2. float:单精度浮点型,精度次之,可以表示的数范围较大,精确到小数点后6~7位。
  3. long:长整型,可以表示的整数范围很大,从-9223372036854775808到9223372036854775807。
  4. int:整型,可以表示的整数范围较大,从-2147483648到2147483647。
  5. short:短整型,表示的整数范围较小,从-32768到32767。
  6. byte:字节型,表示的整数范围最小,从-128到127。
  7. char:字符型,虽然它是用来表示Unicode字符的,不过由于它在底层是以一个无符号的16位整数存储,理论上可以视作从0到65535的范围,但是它主要用于表示字符而不是数值,所以在这个列表中的位置比较特殊。如果只从数值的角度考虑,则可以考虑它大致位于shortint之间,但实际用途有所不同。

这里重点是基于能表示的数值范围和精确度进行排序。需要注意的是,精确度主要是指浮点数(float和double)的精确度,而对于整数类型(byte, short, int, long)则主要考虑的是它们能表示的数值范围。而char主要用于表示字符,但在某些语境下也可能被用作数值处理。

Java 中的常用算术运算符包括以下几种:

  1. 加号 +:用于两个数值的加法运算,或者用于字符串的连接操作。

  2. 减号 -:用于两个数值的减法运算。

  3. 乘号 *:用于两个数值的乘法运算。

  4. 除号 /:用于两个数值的除法运算。如果两个操作数都是整数,则执行整数除法,结果为商的整数部分;如果至少有一个操作数为浮点数,则执行浮点除法。

  5. 取模 %:俗称取余,用于两个数值的取模运算,结果为两数相除后的余数。

  6. 自增 ++:将变量的值增加 1,分为前缀形式(例如++i,先进行自增运算,再返回运算后的值)与后缀形式(例如i++,先返回当前值,然后再进行自增运算)。

  7. 自减 --:将变量的值减少 1,也分为前缀形式(例如--i)与后缀形式(例如i--)。

请注意,使用这些运算符时可能需要考虑运算的类型转换和溢出等问题。例如,当两个整数相除时,如果你希望得到浮点数结果,至少需要有一个操作数进行显式或隐式的类型转换为浮点数。

++ii++ ,以及 --ii-- 都是 Java 中的自增和自减运算符,主要的区别在于它们在表达式中的值和它们对原变量的修改时间不同。

  1. ++i(前缀自增):首先,将 i 的值加 1,然后返回加 1 后的 i。这就意味着,如果我们在一个表达式中使用 ++i,那么在这个表达式中,i 的值都是自增后的值。

  2. i++(后缀自增):首先,返回当前的 i,然后再将 i 的值加 1。这就意味着,如果我们在一个表达式中使用 i++,那么在这个表达式中,i 的值都是自增前的值。

同样,

  1. –i(前缀自减):首先,将 i 的值减 1,然后返回减 1 后的 i。这就意味着,如果我们在一个表达式中使用 --i,那么在这个表达式中,i 的值都是自减后的值。

  2. i–(后缀自减):首先,返回当前的 i,然后再将 i 的值减 1。这就意味着,如果我们在一个表达式中使用 i--,那么在这个表达式中,i 的值都是自减前的值。

例如:

int i = 10;
System.out.println(++i); // 输出11, i的值现在是11
i = 10; // 重新赋值
System.out.println(i++); // 输出10,但是 i 的值现在是11

同样,对于自减运算符:

int i = 10;
System.out.println(--i); // 输出9,i的值现在是9
i = 10;  // 重新赋值
System.out.println(i--); // 输出10,但是i的值现在是9

所以,选择使用哪种形式,前缀还是后缀,取决于你是希望在表达式中使用的是变量改变前的值,还是改变后的值。

取模运算,也叫做取余运算,是一种在数学和计算机科学中常见的运算。优先定义在整数集上,是一种求余数的操作。在Java中,取模运算符为 %

取模运算的基本公式为:

a % b = a − F l o o r ( a / b ) ∗ b a \% b = a - Floor(a / b) * b a%b=aFloor(a/b)b

其中,Floor 表示向下取整,a 表示被除数,b 表示除数。

例如:

  • 13 % 5 = 13 - Floor(13 / 5) * 5 = 13 - 2 * 5 = 3。因此,13 除以 5 的余数是3。

在特定的数学和计算机科学应用中,取模运算有很多用途。例如,在哈希函数或者散列函数中,取模运算常用于将大的数值范围映射到小的数值范围(例:数组的索引)。同样,它也在循环队列和循环数组中发挥着重要的作用,可以简化在数组末尾和开头之间的过渡。

举例:

[root@master ~/java/javacode]# vim  ArithmeticOperator.java
public class ArithmeticOperator{
        public static void main(String[] args){
                System.out.println(10 / 4);
                double a =  10;
                System.out.println(a / 4);
                //默认按照最大精度进行计算
                System.out.println(10.0 / 4);

                //算术
                //单独情况下i++ 与++i是一样的
                int i = 10;
                //i++; // ==> 11
                //++i; // ==> 11
                System.out.println(i);

                //取模:a % b ==> a - a / b * b
                System.out.println(10 % 3); // 1
                System.out.println(10 % -3); // 1
                System.out.println(-10 % 3); // -1


                /*
                作为表达式使用:
                前++:先自增,后赋值
                后++:先赋值,后自增
                */
                int j = 10;
                //int f = j++; //f=j;j=j+1   f=10    j=11
                int f = ++j; //j=j+1;f=j  f=11    j=11
                System.out.println("f="+f+"\tj="+j);
        }
}

在这里插入图片描述
在Java中,逻辑运算符用于连接两个或多个布尔表达式,其结果也是布尔值(truefalse)。以下是Java中的几种基本逻辑运算符及其规则:

  1. && - 逻辑与(AND)运算符:

    • 如果两个操作数都为 true,结果为 true
    • 如果任何一个操作数为 false,结果为 false
    • && 是短路运算符,如果第一个操作数为 false,它将不会评估第二个操作数。
  2. || - 逻辑或(OR)运算符:

    • 如果两个操作数中任意一个为 true,结果为 true
    • 如果两个操作数都为 false,结果为 false
    • || 也是短路运算符,如果第一个操作数为 true,它将不会评估第二个操作数。
  3. ! - 逻辑非(NOT)运算符:

    • 如果操作数为 true,结果为 false
    • 如果操作数为 false,结果为 true

以下是一些逻辑运算符的使用示例:

boolean a = true;
boolean b = false;

// 逻辑与
boolean resultAnd = a && b; // 结果为 false,因为 b 是 false

// 逻辑或
boolean resultOr = a || b; // 结果为 true,因为 a 是 true

// 逻辑非
boolean resultNot = !a; // 结果为 false,因为 a 的取反是 false

使用逻辑运算符时需要特别注意操作符的短路行为,这在编写条件语句时非常有用,可以避免不必要的计算,例如,避免在条件判断中调用一个可能导致异常的方法:

if (obj != null && obj.someMethod()) {
    // 只有当 obj 不为 null 时才会调用 someMethod 方法.
}

在上面的代码中,如果 objnull,由于 && 的短路特性,将不会调用 someMethod 方法。这样可以有效避免 NullPointerException 的发生。

好的,我将通过例子来详细说明逻辑与(&)与短路与(&&),以及逻辑或(|)与短路或(||)之间的区别。

逻辑与&和短路与&&的比较

首先定义两个方法,这些方法会在被调用时打印一条信息,并返回布尔值:

public class LogicalDemo {
    public static void main(String[] args) {
        boolean result;
        boolean a, b;
        
        a = false;
        b = true;

        System.out.println("逻辑与 & 的操作:");
        result = testA(a) & testB(b);
        // 在这里,无论testA()的结果如何,testB()都将被执行

        System.out.println("\n短路与 && 的操作:");
        result = testA(a) && testB(b);
        // 在这里,如果testA()返回false,testB()不会被执行
    }

    public static boolean testA(boolean a) {
        System.out.println("testA 方法被调用,返回:" + a);
        return a;
    }

    public static boolean testB(boolean b) {
        System.out.println("testB 方法被调用,返回:" + b);
        return b;
    }
}

输出:

逻辑与 & 的操作:
testA 方法被调用,返回:false
testB 方法被调用,返回:true

短路与 && 的操作:
testA 方法被调用,返回:false

逻辑或|和短路或|| 的比较

类似地,我们可以使用同样的方法来展示逻辑或和短路或的区别:

        a = true;
        b = false;

        System.out.println("逻辑或 | 的操作:");
        result = testA(a) | testB(b);
        // 在这里,无论testA()的结果如何,testB()都将被执行

        System.out.println("\n短路或 || 的操作:");
        result = testA(a) || testB(b);
        // 在这里,如果testA()返回true,testB()不会被执行

输出:

逻辑或 | 的操作:
testA 方法被调用,返回:true
testB 方法被调用,返回:false

短路或 || 的操作:
testA 方法被调用,返回:true

在上面的示例中,可以看到:

  • 当使用逻辑与&时,不论testA()的结果如何,testB()都会被执行。
  • 当使用短路与&&时,由于testA()返回falsetestB()不会被执行,因为&&操作符已经确定整个表达式的结果必定是false
  • 当使用逻辑或|时,不论testA()的结果如何,testB()都会被执行。
  • 当使用短路或||时,由于testA()返回truetestB()不会被执行,因为||操作符已经确定整个表达式的结果必定是true

从这些例子中可以明显看出短路行为对程序执行流程的影响。使用短路逻辑与&&和短路逻辑或||通常可以提高效率,特别是当第二个操作数的计算代价高昂或者具有潜在副作用时(比如修改状态或进行I/O操作)。

例子1:

public class RelationalOperator{
        public static void main(String[] args){
//              int a = 1;
//              int b = 3;
//              boolean f = b < 3;
//              System.out.println(f);

                //demo01:
                boolean a = false;
                boolean b = true;
                boolean result , result2;
                //logic
                result = test1(a) && test2(b) ;
                result2 = test1(a) & test2(b) ;

                int a1 = 1;
                int b1 = 10;
                //短路与&&
                if ( a1 < 1 && b1++ < 90){
                System.out.println("ok");
                }
                System.out.println("a1="+a1+"\tb1="+b1);
                //逻辑与&
                if ( a1 < 1 & b1++ < 90){
                System.out.println("ok");
                }
                System.out.println("a1="+a1+"\tb1="+b1);
        }
                //定义一个方法
        public static boolean test1(boolean a){
                System.out.println("返回test1==>:"+a);
                return a;
        }
        public static boolean test2(boolean b){
                System.out.println("返回test2==>:"+b);
                return b;
        }
}

运行结果:

[root@master ~/java/javacode]# javac RelationalOperator.java  &&java RelationalOperator
返回test1==>:false
返回test1==>:false
返回test2==>:true
a1=1    b1=10
a1=1    b1=11

例子2:

[root@master ~/java/javacode]# vim RelationalOperator03.java
public class RelationalOperator03{
        public static void main(String[] args){
        int a = 100;
        int b = 10;
        //逻辑非(NOT)
        System.out.println(!(a<10)); // T
        System.out.println(!(a>10)); // F
		//异或
        System.out.println((a < 10)^(b <=10));
        }
}

结果:

[root@master ~/java/javacode]# javac  RelationalOperator03.java && java RelationalOperator03
true
false
true

例子3:

public class RelationalOperator03{
        public static void main(String[] args){
        int a = 100;
        int b = 10;
        if (++a==101 && ++b ==11){
                a =120;

        }
        System.out.println("a="+a+"\tb="+b);
        }
}

结果:

a=120   b=11

例子4:

public class RelationalOperator03{
        public static void main(String[] args){
        int a = 100;
        int b = 10;
        if (a++==101 & ++b ==11){
                a =120;

        }
        System.out.println("a="+a+"\tb="+b);
        }
}

结果:

a=101   b=11

例子5:

public class RelationalOperator03{
        public static void main(String[] args){
        int a = 100;
        int b = 10;
        if (a++==100 || ++b ==10){
                a =120;

        }
        System.out.println("a="+a+"\tb="+b);
        }
}

结果:

a=120   b=10

例子6:

public class RelationalOperator03{
        public static void main(String[] args){
        int a = 100;
        int b = 10;
        if (a++==100 | ++b ==10){
                a =120;

        }
        System.out.println("a="+a+"\tb="+b);
        }
}

结果:

a=120   b=11

例子7:

public class RelationalOperator03{
        public static void main(String[] args){
        boolean x =true;
        boolean y = false;
        short z = 46;
        if ((y = true) && (z++==46)) z++;
        if ((x = false) || (++z==49)) z++;
        System.out.println("x="+x+"\ty="+y+"\tz="+z);
        }
}

结果:

x=false y=true  z=50

三元运算符

Java 中的三元运算符(ternary operator)是唯一的一个条件运算符,它包含三个操作数,可以用于代替简单的 if-else 语句,以实现代码简化。它的一般形式如下:

variable = Expression1 ? Expression2 : Expression3;

这里的工作原理解释如下:

  • Expression1:这是一个布尔表达式,决定了接下来的计算路径,如果表达式为 true,将执行 Expression2,否则执行 Expression3
  • Expression2:这是 Expression1true 时被赋值给 variable 的值。
  • Expression3:这是 Expression1false 时被赋值给 variable 的值。

使用三元运算符时需要特别注意以下几点:

  1. 表达式的类型必须是兼容的:Expression2Expression3 应该返回兼容类型的值,或可自动转换为变量类型。否则,可能导致编译错误。

  2. 三元运算符可以嵌套:但为了阅读和维护的便利性,应尽量避免复杂的嵌套,因为它会使代码难以阅读。

  3. 三元运算符是右结合的:意味着嵌套的三元运算符会从右向左进行求值。

  4. 三元运算符无法替代所有的 if-else 逻辑:仅在条件下根据不同的真值选择不同的值时使用,不应用于复杂的程序逻辑或执行多条语句。

下面是一个简单的例子1:

int a = 5;
int b = 10;
int max = (a > b) ? a : b; // 如果a大于b,max值为a,否则为b

例子2:

public class TernaryOperator{
        public static void main(String[] args){
                int a = 10 , b = 99;
                int result = a > b ? a++ : b--;//b--:先进行赋值:result=b ==> 99;在进行b--操作:b=b-1 ==> 98;
                System.out.println("result="+result+"\ta="+a+"\tb="+b);
        }
}

运行结果:

result=99       a=10    b=98

例子3:

public class TernaryOperator{
        public static void main(String[] args){
                int a = 10 , b = 99;
                int result = a > b ? a++ : --b; //--b:先计算b=b-1 ==>98;在进行赋值:result=b ==> 98;
                System.out.println("result="+result+"\ta="+a+"\tb="+b);
        }
}

运行结果:

result=98       a=10    b=98

例子4:

public class TernaryOperator{
        public static void main(String[] args){
                int a = 10 , b = 99;
                int result = a < b ? a++ : --b;
                System.out.println("result="+result+"\ta="+a+"\tb="+b);
        }
}

运行结果:

result=10       a=11    b=99

例子5:

public class TernaryOperator{
        public static void main(String[] args){
                int a = 10 , b = 99;
                int result = a < b ? ++a : b--;
                System.out.println("result="+result+"\ta="+a+"\tb="+b);
        }
}

运行结果:

result=11       a=11    b=99

在使用时,不仅要考量代码的简洁性,还要保持代码的可读性和后期维护的方便性。

特性:三元运算符数据类型强转
例子:

public class TernaryOperator02{
        public static void main(String[] args){
                int a = 10 , b = 99;
                double result = a < b ? 1.1 : b; //double result = a;
                System.out.println("result="+result+"\ta="+a+"\tb="+b);
        }
}

运行结果:

result=1.1      a=10    b=99
三元运算符作业

比较3个数,并返回最大值:
解题思路:

  • n1 与 n2 做比较得出其中较大的值;
  • n3 与 n2/n1中的较大值比较,返回较大值
public class TernaryOperatorExercise{
        public static void main(String[] args){
                int a = 10 , b = 123 , c = 321;
                //1. n1 与 n2 做比较得出其中较大的值;
                int result = a > b ? a : b ;
                //2. n3 与 n2/n1中的较大值比较,返回较大值
                int result2 = c > result ? c :result;
                System.out.println("result="+result+"\nresult2="+result2);
        }
}

运行结果:

result=123
result2=321

用一条语句解决:

public class TernaryOperatorExercise{
        public static void main(String[] args){
                int a = 10 , b = 123 , c = 321;
                int result2 = c > (a > b ? a : b) ?
                				c :(a > b ? a : b);
                System.out.println("result2="+result2);
        }
}

运算优先符

在程序设计中,运算符优先级决定了表达式中各个运算符的运算顺序。了解和掌握每种运算符的优先级是非常重要的,因为它决定了如何对表达式进行求值。下面是一些常见编程语言(如C/C++、Java、Python等)中运算符的优先级列表,从**高到低排序**(使用“R-->L”表示从右向左运算,使用“L->R”表示从左向右运算)

下面是更新后的表格:

优先级类别运算符描述运算方向
1括号()表达式内的括号优先计算L–>R
2成员访问.->对象和指针成员访问L–>R
3单目运算符!~+(正)、-(负)、++(前置)、--(前置)、*(解引用)、&(取地址)单个操作数的运算符R–>L
4类型转换类型转换操作(int), (double)L–>R
5乘除模*/%乘法、除法、取模运算L–>R
6加减法+-加法、减法L–>R
7位移运算<<>>左右位移L–>R
8关系比较<><=>=大小比较L–>R
9相等比较==!=等于、不等于比较L–>R
10位运算&^、``按位与、异或、或
11逻辑运算&&、``
12条件运算符?:三元条件运算R->L
13赋值运算符=+=-=*=/=%=<<=>>=&=^=、`=`赋值及其复合形式
14逗号,表达式分隔符L->R

每个运算符的运算方向决定了如果有多个同级运算符出现在一个表达式中,它们是如何顺序执行的。

命名规则

在Java编程语言中,标识符(Identifier)是用于标识变量、函数、类等实体的名称。命名规则和规范如下:

  1. 合法字符

    • 标识符只能包含字母(A-Z, a-z)、数字(0-9)、下划线(_)和美元符号($)。
    • 标识符不能以数字开头。
  2. 区分大小写

    • Java是区分大小写的语言,因此MyVariablemyvariable是两个不同的标识符。
  3. 长度限制

    • 标识符的长度不受限制,但过长的标识符会影响代码的可读性。
  4. 关键字和保留字

    • 标识符不能使用Java的关键字(如class, public, void, 等)和保留字。
    • 关键字
      在这里插入图片描述
    • 保留字在这里插入图片描述

命名规范

虽然命名规则规定了标识符的合法性,但为了保持代码的可读性和一致性,通常还会遵循一些命名规范:

  1. 类名

    • 使用大写开头的驼峰命名法(Pascal Case)。
    • 示例:MyClass, EmployeeDetails
  2. 变量名和方法名

    • 使用小写开头的驼峰命名法(Camel Case)。
    • 示例:myVariable, calculateSalary
  3. 常量

    • 使用全大写字母和下划线分隔词。
    • 示例:MAX_VALUE, PI
  4. 包名

    • 规范是使用全小写字母,并且层级由点号分隔。
    • 通常以公司域名的反转形式开始。
    • 示例:com.example.myapp
  5. 接口名

    • 通常也使用大写开头的驼峰命名法,并且可以使用形容词形式。
    • 示例:Runnable, Iterable
public class Employee {
    private String name;
    private int age;
    private static final int MAX_AGE = 65;

    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age <= MAX_AGE) {
            this.age = age;
        }
    }
    
    public static void main(String[] args) {
        Employee emp = new Employee("John", 30);
        System.out.println("Name: " + emp.getName());
        System.out.println("Age: " + emp.getAge());
    }
}

在这个示例中:

  • Employee是一个类名,使用大写开头的驼峰命名法。
  • name, age是变量名,使用小写开头的驼峰命名法。
  • MAX_AGE是常量,使用全大写字母和下划线。
  • 方法名如getName, setName, main使用小写开头的驼峰命名法。

扫描器

在这里插入图片描述
示例:

//导入Scanner类,属于util包里面
import java.util.Scanner;
public class myScanner {
    public static void main(String[] args) {
    	//新建一个Scanner对象myScannner
        Scanner myScanner = new Scanner(System.in);
        System.out.println("################输入人员信息###############");
        System.out.println("输入姓名:");
        String name = myScanner.next();
        System.out.println("姓名:" + name);
        System.out.println("输入年龄:");
        int age = myScanner.nextInt();
        System.out.println("年龄:" + age);
        System.out.println("输入薪资:");
        double sty = myScanner.nextDouble();
        System.out.println("薪资:" + sty);
      //System.out.println("姓名:" + name +"\t年龄:"+ age +"\t薪资:"+ sty );
    	 System.out.printf("姓名:%s\t年龄:%d\t薪资:%.2f",name,age,sty);
    }
}

运行结果:

################输入人员信息###############
输入姓名:
liha
姓名:liha
输入年龄:
21
年龄:21
输入薪资:
10000.1
薪资:10000.1
姓名:liha       年龄:21 薪资:10000.1

进制介绍

在这里插入图片描述
以下是二进制八进制十进制十六进制的对应表格:

十进制 (Decimal)二进制 (Binary)八进制 (Octal)十六进制 (Hexadecimal)
0000000
1000111
2001022
3001133
4010044
5010155
6011066
7011177
81000108
91001119
10101012A
11101113B
12110014C
13110115D
14111016E
15111117F
16100002010

下面详细介绍一下进制之间的转换及相关技巧

一、十进制转换为其他进制
1. 十进制转换为二进制
  • 方法:将十进制数不断除以2,取余数,直到商为0,然后将余数逆序排列

  • 例子:把10转换为二进制

    1. 10 ÷ 2 = 5,余0
    2. 5 ÷ 2 = 2,余1
    3. 2 ÷ 2 = 1,余0
    4. 1 ÷ 2 = 0,余1

    最终结果: 1 0 10 = 101 0 2 10_{10} = 1010_{2} 1010=10102

2. 十进制转换为八进制
  • 方法:将十进制数不断除以8,取余数,直到商为0,然后将余数逆序排列

  • 例子:把83转换为八进制

    1. 83 ÷ 8 = 10,余3
    2. 10 ÷ 8 = 1,余2
    3. 1 ÷ 8 = 0,余1

    最终结果: 8 3 10 = 12 3 8 83_{10} = 123_{8} 8310=1238

3. 十进制转换为十六进制
  • 方法:将十进制数不断除以16,取余数,直到商为0,然后将余数逆序排列(注意用A、B、C、D、E、F表示10、11、12、13、14、15)。
  • 例子:把254转换为十六进制
    1. 254 ÷ 16 = 15,余14(E)
    2. 15 ÷ 16 = 0,余15(F)
      最终结果: 25 4 10 = F E 16 254_{10} = FE_{16} 25410=FE16
  • 例子: 把983转换为十六进制
    1. 16 61 余 … 7
    2. 16 3 余… 13 (D)
      最终结果: 98 3 10 = 3 D 7 16 983_{10} = 3D7_{16} 98310=3D716
二、其他进制转换为十进制
1. 二进制转换为十进制
  • 方法:将二进制数每位上的数字乘以2的对应次幂,然后求和。
  • 例子:把1010转换为十进制
    101 0 2 = 1 × 2 3 + 0 × 2 2 + 1 × 2 1 + 0 × 2 0 = 8 + 0 + 2 + 0 = 1 0 10 1010_{2} = 1 \times 2^3 + 0 \times 2^2 + 1 \times 2^1 + 0 \times 2^0 = 8 + 0 + 2 + 0 = 10_{10} 10102=1×23+0×22+1×21+0×20=8+0+2+0=1010
2. 八进制转换为十进制
  • 方法:将八进制数每位上的数字乘以8的对应次幂,然后求和。
  • 例子:把123转换为十进制
    12 3 8 = 1 × 8 2 + 2 × 8 1 + 3 × 8 0 = 64 + 16 + 3 = 8 3 10 123_{8} = 1 \times 8^2 + 2 \times 8^1 + 3 \times 8^0 = 64 + 16 + 3 = 83_{10} 1238=1×82+2×81+3×80=64+16+3=8310
3. 十六进制转换为十进制
  • 方法:将十六进制每位上的数字乘以16的对应次幂,然后求和(字母A-F对应十进制的10-15)。
  • 例子:把FE转换为十进制
    F E 16 = 15 × 1 6 1 + 14 × 1 6 0 = 240 + 14 = 25 4 10 FE_{16} = 15 \times 16^1 + 14 \times 16^0 = 240 + 14 = 254_{10} FE16=15×161+14×160=240+14=25410
三、其他进制之间的转换
1. 二进制转换为八进制
  • 方法:将二进制数每三位一组(从右向左)分组,不足三位的左边补零,每组转换为对应的八进制数。

  • 例子:把101010转换为八进制

    1. 分组:101 010
    2. 组转换: 10 1 2 = 5 8 101_2 = 5_8 1012=58, 01 0 2 = 2 8 010_2 = 2_8 0102=28

    最终结果: 10101 0 2 = 5 2 8 101010_{2} = 52_{8} 1010102=528

2. 二进制转换为十六进制
  • 方法:将二进制数每四位一组(从右向左)分组,不足四位的左边补零,每组转换为对应的十六进制数。

  • 例子:把110101转换为十六进制

    1. 分组:0011 0101
    2. 组转换: 001 1 2 = 3 16 0011_2 = 3_{16} 00112=316, 010 1 2 = 5 16 0101_2 = 5_{16} 01012=516

    最终结果: 11010 1 2 = 3 5 16 110101_{2} = 35_{16} 1101012=3516

3. 八进制转换为二进制
  • 方法:将八进制数每个数字转换为三位二进制数。

  • 例子:把52转换为二进制

    1. 5 8 = 10 1 2 5_8 = 101_2 58=1012
    2. 2 8 = 01 0 2 2_8 = 010_2 28=0102

    最终结果: 5 2 8 = 10101 0 2 52_{8} = 101010_{2} 528=1010102

4. 十六进制转换为二进制
  • 方法:将十六进制数每个数字转换为四位二进制数。

  • 例子:把3E转换为二进制

    1. 3 16 = 001 1 2 3_{16} = 0011_2 316=00112
    2. E 16 = 111 0 2 E_{16} = 1110_2 E16=11102

    最终结果: 3 E 16 = 0011111 0 2 3E_{16} = 00111110_{2} 3E16=001111102

原码、反码、补码

在这里插入图片描述
原码

原理:

  • 源码是一种最基础的二进制编码方式,直接根据数值的正负进行表示。对于正数,源码就是其二进制表示;对于负数,源码在正数二进制表示的基础上将最高位设为1,来表示负号。

规则:

  • 最高位为符号位:0表示正数,1表示负数
  • 其余位为数值部分的二进制表示

反码

原理:

  • 反码是在源码的基础上,将数值部分(除符号位以外)逐位取反,1变成0,0变成1。

规则:

  • 对于正数,反码与源码相同。
  • 对于负数,符号位保留,其余位逐位取反。

补码

原理:

  • 补码是在反码的基础上加1,是计算机处理中负数的标准表示方式,因为补码运算可以简化加减运算。

规则:

  • 对于正数,补码和源码相同。
  • 对于负数,在反码的基础上加1。
位运算

在这里插入图片描述
下面采用一个例子更好的理解源码、反码和补码的原理。

实例说明 ~2~-2 的计算过程
假设使用 int 数据类型(在大多数编程语言中,int 通常占用32位)进行以下示例。

1. 计算 2 的源码、反码、补码

十进制数 2 在二进制下的表示为:00000000 00000000 00000000 00000010

  • 源码(原码):

    • 2 的源码为:00000000 00000000 00000000 00000010
  • 反码:

    • 对于正数,反码与源码相同:00000000 00000000 00000000 00000010
  • 补码:

    • 对于正数,补码与源码相同:00000000 00000000 00000000 00000010
2. 按位取反 ~2 的结果

按位取反 ~2

  • 取反每一位:11111111 11111111 11111111 11111101
3. 结果转换回十进制

由于最高位是1,表示这是一个负数:

  • 先找到其补码对应的负数:
    • 反码:00000000 00000000 00000000 00000010
    • 加 1:00000000 00000000 00000000 00000011
    • 对应十进制数为 3
  • 因为符号位为1,表示负数,所以结果为 -3

结论:~2 按位取反后的十进制结果为 -3

4. 计算 -2 的源码、反码、补码

十进制数 -2 的计算过程:

  • 源码:

    • -2 的源码为:10000000 00000000 00000000 00000010
  • 反码:

    • 除符号位外逐位取反:11111111 11111111 11111111 11111101
  • 补码:

    • 在反码基础上加1:11111111 11111111 11111111 111111#### 5. 按位取反 ~-2` 的结果
  • 取反每一位:00000000 00000000 00000000 00000001

5. 结果转换回十进制

由于这是一个正数(最高位为0),直接转换:

  • 二进制 00000000 00000000 00000000 00000001 对应十进制为 1

结论:~-2 按位取反后的十进制结果为 1

综合总结
通过源码、反码和补码的原理和具体示例计算,得到以下结果:

  • 2 的源码、反码和补码:00000000 00000000 00000000 00000010
  • ~2 在转换为十进制后的结果为 -3
  • -2 的源码:10000000 00000000 00000000 00000010
  • -2 的反码:11111111 11111111 11111111 11111101
  • -2 的补码:11111111 11111111 11111111 11111110
  • ~-2 在转换为十进制后的结果为 1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1806838.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux基础 (十五):TCP 协议特点和UDP协议

上一节&#xff0c;我们学习了TCP协议的服务器-客户端的编程流程以及对中间的过程进行了详细的讨论&#xff0c;那么&#xff0c;这一节&#xff0c;我们对于TCP协议的特点进行进一步的分析&#xff0c;这也是面试的重点和难点。 目录 一、TCP 协议特点 1.1 连接的建立与断…

【内网攻防实战】红日靶场(一)续篇_金票与银票

红日靶场&#xff08;一&#xff09;续篇_权限维持 前情提要当前位置执行目标 PsExec.exe拿下域控2008rdesktop 远程登录win7msf上传文件kail回连马连上win7upload上传PsExec.exe PsExec.exe把win7 带到 2008&#xff08;域控hostname&#xff1a;owa)2008开远程、关防火墙Win7…

汇编:数组-寻址取数据

比例因子寻址&#xff1a; 比例因子寻址&#xff08;也称为比例缩放索引寻址或基址加变址加比例因子寻址&#xff09;是一种复杂的内存寻址方式&#xff0c;常用于数组和指针操作。它允许通过一个基址寄存器、一个变址寄存器和一个比例因子来计算内存地址。 语法 比例因子寻…

Java Web学习笔记30——打包部署

打包&#xff1a; 到资源管理器中再看下&#xff1a; 将这些文件压缩成一个zip文件&#xff0c;然后到nginx的html目录中执行unzip 解压即可。 部署&#xff1a; Nginx&#xff1a;Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代…

FreeRTOS基础(十三):队列集

队列集&#xff08;Queue Set&#xff09;通常指的是一组队列&#xff0c;它们可以用于处理不同的任务或数据流。每个队列可以独立地处理自己的元素&#xff0c;但作为一个集群&#xff0c;它们可以协同工作来完成更复杂的任务。下面进行介绍。 目录 一、队列集简介 二、队列…

OPenCV的重要结构体Mat

一 Mat Mat是什么&#xff1f; Mat有什么好处&#xff1f; class CV_EXPORTS Mat{ public: ... int dims;//维数 int rows,cols;//行列数 uchar *data;//存储数据的指针 int *refcount;//引用计数 ...};二 Mat属性 三 Mat拷贝 1 Mat浅拷贝 Mat A Aimread(file,IMREAD_COLOR) …

标准发布实施 |《新能源电池工业废水处理技术指南磷酸铁锂电池》

T/ACEF 130&#xff0d;2024《新能源电池工业废水处理技术指南磷酸铁锂电池》欢迎各单位引用执行&#xff01;有课题也可联合立项&#xff01; 发布日期&#xff1a;2024年02月04日 实施日期&#xff1a;2024年03月01日 主要起草人&#xff1a;刘愿军、孙冬、丁炜鹏、何小芬…

《解决方案架构师修炼之道》读书笔记

1. 水在前面 第一次看到“解决方案架构师”这个词&#xff0c;就把这本书借回家翻了。最近也在网上看点资料&#xff0c;对比起来发现还是出版物内容更完整和更有体系&#xff0c;而且看书真的能让人安静下来。。。 《解决方案架构师修炼之道》所罗伯死里瓦斯塔瓦&#xff0c;内…

Centos修改默认端口22

修改Centos服务器ssh链接的默认端口22到任意端口&#xff0c;主要两个步骤&#xff1a; 修改配置文件&#xff0c;添加端口开放防火墙 一、 vim /etc/ssh/sshd_config 在文件中 #Port 22 行下增加 # Port 22 Port [修改后端口]注意&#xff1a; 这里 先将其中的#Port 22前的…

!力扣102. 二叉树的层序遍历

给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]] /*** Definition for…

计算机组成原理之指令寻址

一、顺序寻址 1、定长指令字结构 2、变长指令字结构 二、跳跃寻址 三、数据寻址 1、直接寻址 2、间接寻址 3、寄存器寻址 寄存器间接寻址 4、隐含寻址 5、立即寻址 6、偏移寻址 1、基址寻址 2、变址寻址 3、相对寻址

C++程序设计:对数据文件的操作与文件流

姚老师小课堂开课啦&#xff01; 一、文件的分类&#xff1a; 1.ASCII码文件&#xff1a; ASCII文件使用方便&#xff0c;比较直观&#xff0c;便于阅读&#xff0c;便于对字符进行输入输出&#xff0c;但一般占用存储空间较多&#xff0c;而且需要花费转换时间&#xff08;二…

【JAVASE】面向对象编程综合案例--------模仿电影信息系统

需求&#xff1a; &#xff08;1&#xff09;展示系统中的全部电影&#xff08;每部电影展示&#xff1a;名称、价格&#xff09; &#xff08;2&#xff09;允许用户根据电影编号&#xff08;ID&#xff09;查询出某个电影的详细信息。 目标&#xff1a;使用所学的面向对象…

问题排查: Goalng Defer 带来的性能损耗

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作)&#xff0c;由 李兆龙 确认&#xff0c;转载请注明版权。 文章目录 引言问题背景结论 引言 性能优化之路道阻且长&#xff0c;因为脱敏规定&#xff0c;…

TinyVision V851s 使用 OpenCV + NPU 实现 Mobilenet v2 目标分类识别

用39块钱的V851se视觉开发板做了个小相机。 可以进行物品识别、自动追焦&#xff01; 这个超低成本的小相机是在V851se上移植使用全志在线开源版本的Tina Linux与OpenCV框架开启摄像头拍照捕获视频&#xff0c;并结合NPU实现Mobilenet v2目标分类识别以及运动追踪等功能......并…

Springboot整合SpringCache+redis简化缓存开发

使用步骤&#xff1a; 1.引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId> </dependency><dependency><groupId>org.springframework.boot</groupI…

定个小目标之刷LeetCode热题(14)

了解股票的都知道&#xff0c;只需要选择股票最低价格那天购入&#xff0c;在股票价格与最低价差值最大时卖出即可获取最大收益&#xff0c;总之本题只需要维护两个变量即可&#xff0c;minPrice和maxProfit&#xff0c;收益 prices[i] - minPrice,直接用代码描述如下 class …

AIRNet模型使用与代码分析(All-In-One Image Restoration Network)

AIRNet提出了一种较为简易的pipeline&#xff0c;以单一网络结构应对多种任务需求&#xff08;不同类型&#xff0c;不同程度&#xff09;。但在效果上看&#xff0c;ALL-In-One是不如One-By-One的&#xff0c;且本文方法的亮点是batch内选择patch进行对比学习。在与sota对比上…

电影制作中的版本控制:Perforce Helix Core帮助某电影短片避免灾难性文件损坏,简化艺术资产管理

Zubaida Nila是来自马来西亚的一名视觉特效师和虚拟制作研究员&#xff0c;她参加了Epic Games的一个为期六周的虚拟培训和指导项目——女性创作者计划。该计划提供了虚幻引擎工作流程的实践经验以及其他课程。Zubaida希望从中获得更多关于虚幻引擎的灯光、后期处理和特效技能方…

csrf与xss差别 别在弄乱了 直接靶场实操pikachu的csrf题 token绕过可以吗???

我们现在来说说这2个之间的关系&#xff0c;因为昨天的我也没有弄清楚这2者的关系&#xff0c;总感觉迷迷糊糊的。 xss这个漏洞是大家并不怎么陌生&#xff0c;导致xss漏洞的产生是服务器没有对用户提交数据过滤不严格&#xff0c;导致浏览器把用户输入的当作js代码返回客户端…