C#表达式和运算符

news2025/1/18 13:56:31

本文我们将学习C#的两个重要知识点:表达式和运算符。本章内容会理论性稍微强些,我们会尽量多举例进行说明。建议大家边阅读边思考,如果还能边实践就更好了。

1. 表达式

说到表达式,大家可能感觉有些陌生,我们先来举个例子。在前面章节的示例代码中,大家一定见过类似这样的代码:i++,它其实就是一个表达式,其中的++是自增运算符,此表达式执行了自增运算让变量i自增1。我们现在来分析一下这个示例表达式的组成:

  1. 操作数,运算符的操作对象,这里是i

  2. 运算符,指明对操作数做何种操作,这里是++

可见,上述表达式的形式是:操作数+运算符。表达式的定义是:具有一个或多个操作数,零个或多个运算符,可以计算且结果为单个值、对象、方法或命名空间的代码片段称作表达式。可见,一个表达式至少有1个操作数,运算符可以没有,且必须有计算结果。一个表达式中,可以包含简单的文本值、方法调用、运算符以及它的操作数,或者一个简单名称。这里的简单名称实际上是一个标识符,它可以是变量名、类型成员、方法参数、命名空间或者类型的名称,如图6-1所示。

由图6-1以及表达式的定义可知,运算符并非必需,下列所示代码也是合法的表达式,例如:

int x = 10;
string name = "Tom";

这里的10"Tom"就是简单的文本值,文本是没有名称的常数值,它们也是表达式。

表达式可以带有运算符,而运算符又可以将其他表达式用作参数,或者使用方法调用,而方法调用的参数又可以是其他方法调用。因此,表达式既可以非常简单,也可以非常复杂。

2. 运算符的类型

在C#中,运算符是术语或符号,它用于单个表达式,或者将多个表达式连接在一起,这些表达式所扮演的角色叫做"操作数"。运算符的重要作用之一就是计算1个或多个表达式,并把计算结果返回。运算符有多种类型,可以根据操作数的数量进行分类:

  1. 一元运算符:接受一个操作数的运算符称作一元运算符,例如增量运算符(++)或new

  2. 二元运算符:接受两个操作数的运算符称作二元运算符,例如算术运算符(+-*/)。

  3. 三元运算符:条件运算符(? :)接受三个操作数,是C#中唯一的三元运算符。

下面我们分别举例进行说明,如图6-2所示。

图6-2中的语句包含3个二元运算符(=+*),它们分别有两个操作数。这3个二元运算符说明如下:

  1. 赋值运算符(=)将一个整数(x)和一个表达式(10 + 2 * 3)作为操作数;

  2. 表达式本身包含加和乘运算符,加(+)运算符使用整数值10和表达式2 * 3作为操作数;

  3. 乘(*)运算符使用整数值23作为操作数。

需要说明的是操作数可以是任何大小的有效表达式。

3. 运算符的优先级

表6-1是C#中的全部运算符,根据操作类型分成了基本运算符、一元运算符、算术运算符等10个类别,并按照类别优先级进行排列。

此行我要插入图片3,做个标记输出给我。

当表达式中出现两个具有相同优先级的运算符时,它们根据结合性进行计算。左结合运算符按从左到右的顺序计算,例如,x * y / z计算为(x * y) / z。右结合运算符按从右到左的顺序计算。赋值运算符和三元运算符(? :)是右结合运算符。其他所有二元运算符都是左结合运算符。

4. 算术运算符

算术运算符有加、减、乘、除以及求余运算符,这里先学习简单的四则运算运算符,如表6-2所示。求余运算符将在6.5节讲述。

代码清单6-1给出了算术运算符的示例。

代码清单6-1 算术运算符示例

using System;

namespace ProgrammingCSharp4
{
    class OperatorSample
    {
        int i1 = 10 + 20;
        int i2 = 20 - 10;
        int i3 = 10 * 20;
        int i4 = 20 / 3;
        double d1 = 1.1 + 2.2;
        double d2 = 1.1 - 2.2;
        double d3 = 1.1 * 2.2;
        double d4 = 1.1 / 2.2;

        static void Main()
        {
            OperatorSample os = new OperatorSample();
            Console.WriteLine("i1={0}", os.i1);
            Console.WriteLine("i2={0}", os.i2);
            Console.WriteLine("i3={0}", os.i3);
            Console.WriteLine("i4={0}", os.i4);
            Console.WriteLine("d1={0}", os.d1);
            Console.WriteLine("d2={0}", os.d2);
            Console.WriteLine("d3={0}", os.d3);
            Console.WriteLine("d4={0}", os.d4);
        }
    }
}

运算结果为:

i1=30
i2=10
i3=200
i4=6
d1=3.3
d2=-1.1
d3=2.42
d4=0.5

5. 求余运算符

求余运算符是把第二个操作数除以第一个操作数,并返回余数。如果整除则返回余数0,不能整除则返回余数,如表6-3所示。

代码清单6-2给出了求余运算符的示例。

代码清单6-2 求余运算符示例

using System;

namespace ProgrammingCSharp4
{
    class OperatorSample
    {
        int i1 = 0 % 20;
        int i2 = 10 % 20;
        int i3 = 20 % 20;
        int i4 = 30 % 20;

        static void Main()
        {
            OperatorSample os = new OperatorSample();
            Console.WriteLine("0%20={0}", os.i1);
            Console.WriteLine("10%20={0}", os.i2);
            Console.WriteLine("20%20={0}", os.i3);
            Console.WriteLine("30%20={0}", os.i4);
        }
    }
}

输出如下:

0%20=0
10%20=10
20%20=0
30%20=10

6. 递增运算符和递减运算符

递增运算符对操作数增加1,递减运算符对操作数减去1,它们分别具有两种形式,分别是运算符前置和运算符后置,如表6-4所示。

我们通过一段代码来说明,如代码清单6-3所示。

代码清单6-3 递增运算符和递减运算符示例

using System;

namespace ProgrammingCSharp4
{
    class OperatorSample
    {
        static void Main()
        {
            int i = 10;
            int i1 = ++i;
            Console.WriteLine("i={0}", i);
            i = 10;
            int i2 = i++;
            Console.WriteLine("i={0}", i);
            i = 10;
            int i3 = --i;
            Console.WriteLine("i={0}", i);
            i = 10;
            int i4 = i--;
            Console.WriteLine("i={0}", i);
            Console.WriteLine("++i={0}", i1);
            Console.WriteLine("i++={0}", i2);
            Console.WriteLine("--i={0}", i3);
            Console.WriteLine("i--={0}", i4);
        }
    }
}

输出如下:

i=11
i=11
i=9
i=9
++i=11
i++=10
--i=9
i--=10

代码清单6-3的第9行定义了变量i,其值为10;第10行定义新的变量i1,执行i变量的前置递增操作(++i);在第11行打印i的新值;第13行将i的值重新设置为初始值10;第14行执行i变量的后置递增操作(i++);同样地,第15行打印i的新值。前置递减和后置递减同理,不再赘述。通过输出结果,我们可以看出,无论是前置还是后置,变量的值都是相同的,不同的就是整个表达式的返回值,如无论前置递增还是后置递增,i值都增加了1变为了11,而递减操作则变为了9,但前置递增返回的是新值11,后置递增返回的是旧值10。因此可以得出如下结论:

  1. 无论是前置还是后置(无论递增还是递减),操作数的值都发生了改变,且值相同(对于前置还是后置递增或递减而言);

  2. 前置操作符返回表达式新值,后置操作符返回表达式旧值。

7. 关系和类型检测运算符

这里讨论的关系为大于、小于、大于等于、小于等于四种关系,等于和不等于关系在9节介绍。既然涉及比较,就意味着关系运算符是二元运算符,即必须有两个操作数。而且,关系运算符的结合性是左结合。

类型检测运算符为asis

关于关系运算符的说明,如表6-5所示。

由表6-5可知,使用了关系运算符的表达式返回bool类型的结果值:true或者false

关系运算符的使用,如代码清单6-4所示。

代码清单6-4 关系运算符示例

using System;

namespace ProgrammingCSharp4
{
    class OperatorSample
    {
        static void Main()
        {
            int i1 = 10;
            int i2 = 10;
            int i3 = 20;
            Console.WriteLine("i1 >= i2 ? {0}", i1 >= i2);
            Console.WriteLine("i1 > i2 ? {0}", i1 > i2);
            Console.WriteLine("i1 < i3 ? {0}", i1 < i3);
            Console.WriteLine("i1 <= i3 ? {0}", i1 <= i2);
        }
    }
}

上述代码的运行结果为:

i1 >= i2 ? True
i1 > i2 ? False
i1 < i3 ? True
i1 <= i3 ? True

8. 相等性判断运算符

相等性判断运算符(==!=)也是二元运算符,并且是左结合,如表6-6所示。

对于值类型数据的判断,相等性判断的依据是两个操作数的值是否相等。而对于引用类型的操作数而言,大多数情况下比较的是它们的引用,而不管它们引用的对象有多么相似,甚至其值相同。

如图6-3所示,在第一个图中,引用a和引用b指向的是同一个对象------类1,因此它们是相等的;而对于第二个图,两个引用指向不同对象,因此它们不相等。但也有例外,string类型是引用类型,但string类型之间比较的是字符串长度和它们的值,其中值是大小写敏感的。

相等性运算符的示例如代码清单6-5所示。

代码清单6-5 相等性运算符示例

using System;

namespace ProgrammingCSharp4
{
    class OperatorSample
    {
        static void Main()
        {
            int i1 = 10;
            int i2 = 10;
            int i3 = 20;
            object o1 = i1;
            object o2 = o1;
            object o3 = i2;
            object o4 = i1;
            string s1 = "hello";
            string s2 = "hello";
            string s3 = "world";
            Console.WriteLine("i1 == i2 ? {0}", i1 == i2);
            Console.WriteLine("i1 != i3 ? {0}", i1 != i3);
            Console.WriteLine();
            Console.WriteLine("o1 == o2 ? {0}", o1 == o2);
            Console.WriteLine("o1 == o3 ? {0}", o1 == o3);
            Console.WriteLine("o1 != o3 ? {0}", o1 != o3);
            Console.WriteLine("o1 == o4 ? {0}", o1 == o4);
            Console.WriteLine();
            Console.WriteLine("s1 == s2 ? {0}", s1 == s2);
            Console.WriteLine("s1 == s3 ? {0}", s1 == s3);
        }
    }
}

上述代码输出结果为:

i1 == i2 ? True
i1 != i3 ? True

o1 == o2 ? True
o1 == o3 ? False
o1 != o3 ? True
o1 == o4 ? False

s1 == s2 ? True
s1 == s3 ? False

难点解析:

  1. o1 和 o2 都指向相同的object实例,因此它们是相等的。所以,o1 == o2 返回true

  2. o1 和 o4 都包装了相同的值(10),但是由于o1o4是不同的对象实例,==操作符默认使用引用比较,比较的是它们是否是同一个实例,而不是它们的值。因此,o1 == o4 返回false

9. 条件运算符

条件运算符用于比较两个操作数的逻辑值,并返回一个逻辑值作为结果,如表6-7所示。

这些运算符的语法如下:

  1. 表达式1 && 表达式2

  2. 表达式1 || 表达式2

  3. !表达式

  4. 布尔表达式 ? 结果1 : 结果2

需要说明的是,条件运算符使用"短路"计算模式。对于逻辑与运算符而言,如果第1个表达式结果为false,那么整个表达式的结果就已经确定了(false),第2个表达式将不会被执行,因此在第2个表达式中放置可能修改变量值的表达式是没有意义的。对于逻辑或运算符而言,如果第1个表达式结果为true,那么整个表达式的结果也已经确定了(true),因此第2个表达式同样不会被执行。

对于C#中唯一的三元运算符(? :)而言,首先计算布尔表达式的值,如果值为true,则整个表达式的结果取结果1,否则取结果2。

下面举例进行说明,如代码清单6-6所示。

代码清单6-6 条件运算符示例

using System;

namespace ProgrammingCSharp4
{
    class OperatorSample
    {
        static void Main()
        {
            Console.WriteLine((1 == 0) && (1 == 1)); // False
            Console.WriteLine((1 == 0) || (1 == 1)); // True
            Console.WriteLine((1 == 0) || (1 == 2)); // False
            Console.WriteLine(!(1 == 0)); // True
            Console.WriteLine((1 == 0) ? 1 : 2); // 2
        }
    }
}

上述代码输出结果为:

False
True
False
True
2

在代码清单6-6中,第9行使用逻辑与运算符(&&),因为第1个表达式(1 == 0)结果为false,那么整个表达式的结果就已确定为false;第10行使用逻辑或运算符(||),虽然第1个表达式(1 == 0)结果为false,但第2个表达式(1 == 1)结果为true,因此整个表达式的结果为true;第11行使用逻辑或运算符,因为两个表达式的结果均为false,因此整个表达式的结果为false;第12行使用逻辑非运算符,因为表达式(1 == 0)的结果为false,那么整个表达式的结果为true;第13行使用三元条件运算符,因为第1个表达式(1 == 0)的结果为false,因此整个表达式的结果取第2个值------2,否则取第1个值。

10. 逻辑运算符

逻辑运算符除了"位与(&既可作为一元运算符也可以作为二元运算符)"和"位非(~)"以外,均为二元左结合运算符,如表6-8所示。

代码清单6-7演示了这些运算符的用法。

代码清单6-7 逻辑运算符示例

using System;

namespace ProgrammingCSharp4
{
    class OperatorSample
    {
        static void Main()
        {
            int i1 = 100;
            int i2 = 101;
            Console.WriteLine("100 & 101 = {0}", i1 & i2);
            Console.WriteLine("100 | 101 = {0}", i1 | i2);
            Console.WriteLine("100 ^ 101 = {0}", i1 ^ i2);
            Console.WriteLine("~100 = {0}", ~i1);
        }
    }
}

上述代码的运行结果如下:

100 & 101 = 100
100 | 101 = 101
100 ^ 101 = 1
~100 = -101

图6-4演示了上述代码的运算过程。

11. 位运算符

位运算符将操作符向左或者向右移动指定数目个位置,空出的位用0填充,如表6-9所示。

位运算符将第一个操作数向左或向右移动第二个操作数所指定的位数,其中第二个操作数的类型必须是int。向左移n位,相当于原值的2的n次方倍;向右移n位,相当于原值的2的n次方倍分之1。如图6-5所示,表达式100 << 2相当于100 × 2^2 = 400

代码清单6-8演示了位运算符的使用。

代码清单6-8 位运算符示例

using System;

namespace ProgrammingCSharp4
{
    class OperatorSample
    {
        static void Main()
        {
            int i1 = 100;
            int i2 = i1 << 2;
            Console.WriteLine(i2);
        }
    }
}

输出结果如下:

400

图6-5演示了上述代码的运算过程。

12. 赋值运算符

赋值运算符使用左右2个操作数,左侧的操作数为一个变量,右侧的操作数是一个有效的表达式,当右侧的表达式计算出结果,将会根据"赋值"运算符的类别,与左侧变量一起进行某种运算,然后把结果赋予左侧变量,具体如表6-10所示。

由表6-10可知,使用赋值运算符的语法如下:

复制

变量 赋值运算符 表达式;

其中,位与赋值运算符左边除了可以是变量以外,还可以为以下类型:

  1. 属性(类级别字段,带访问器)

  2. 索引

  3. 事件

基本赋值运算符(=)我们已经使用了很多次,相信大家已经熟悉了,如:

int i1 = 100;
int i2 = 101;

意即将100赋给int类型的变量i1,将101赋给int类型变量i2。另外一种情况可能比简单赋值稍微复杂些,就是首先计算一个表达式的值,然后将它和某个变量一起进行计算。主要有两种方式:

  1. 将表达式的值使用基本赋值运算符赋给某一个变量,然后将该变量和既定变量进行计算;

  2. 使用复合赋值运算符,如+=-=*=等等。

以下两种方式是等价的:

i = i + 100;
i += 100;

显然,第2种方式更简洁。其中+=运算符还可以连接两个字符串,如:

string s = "Hello";
s += "world!";
Console.WriteLine(s);

下面两种方式也是等价的,这说明复合赋值运算符操作的是右侧表达式的计算结果,而不是其中某个操作数。

i3 *= i1 + i2;
i3 *= (i1 + i2);

这里有一个特殊的赋值运算符??,它是一个二元运算符,当左操作数为空时返回右操作数,否则返回左操作数。需要注意的是,该运算符只能应用于引用类型或Nullable(可空)类型,如:

string a = "hello world!";
string b = a ?? "hello C#!";
Console.WriteLine(b);

上述代码的运行结果为:

hello world!

13. typeof运算符

typeof是一元运算符,用于返回任意一个类型的类型信息(使用System.Type对象表示),如表6-11所示。

typeof运算符的语法如下:

Type type = typeof(类型);

下面,通过一个示例来看看typeof运算符的用法,如代码清单6-9所示。

代码清单6-9 typeof运算符示例

using System;
using System.Reflection;

namespace ProgrammingCSharp4
{
    class OperatorSample
    {
        static void Main()
        {
            Type t = typeof(OperatorSample);
            Console.WriteLine("方法:");
            MethodInfo[] methodInfo = t.GetMethods();
            foreach (MethodInfo mInfo in methodInfo)
            {
                Console.WriteLine(mInfo.ToString());
            }
            Console.WriteLine("成员:");
            MemberInfo[] memberInfo = t.GetMembers();
            foreach (MemberInfo mInfo in memberInfo)
            {
                Console.WriteLine(mInfo.ToString());
            }
        }
    }
}

上述代码的输出结果如下:

方法:
System.String ToString()
Boolean Equals(System.Object)
Int32 GetHashCode()
System.Type GetType()
成员:
System.String ToString()
Boolean Equals(System.Object)
Int32 GetHashCode()
System.Type GetType()
Void.ctor()

14. 运算符重载

前面讲的运算符都有一个共同点,即它们只能使用框架预定义类型作为操作数,如果想要对自定义类型进行操作该怎么办呢?和C++一样,C#同样支持运算符重载,以处理此类问题。例如,可以创建一个名为ComplexNumber的新数据类型来表示一个复杂的数字,并提供使用标准算术运算符对此类数字执行数学运算的方法,如使用加(+)运算符将两个复杂数字相加。

可见,使用运算符重载给开发人员带来了如下好处:

  1. 使代码更加容易理解和阅读;

  2. 可以利用现有运算符的优先级关系规则处理对象之间的运算;

  3. 使代码更加灵活,对象可操作性更好。

下面将详细阐述如何实现运算符重载。

14.1 运算符的重载

运算符重载只能应用于类或结构。要重载一个运算符,可以声明一个名为operator x的方法并实现它,如operator+operator-,一元运算符和二元运算符都可以被重载,相应地,重载方法分别带一个或两个参数(类或结构类型),其语法为:

// 一元运算符重载
public static 自定义类型 operator 要重载的运算符(类型)

// 二元运算符重载
public static 自定义类型 operator 要重载的运算符(类型1, 类型2)

如:public static OperatorSample operator+(OperatorSample obj)

需要注意的是,所有运算符重载均为类的静态方法,且必须使用public进行修饰。

注意:重载相等运算符(==)时,还必须重载不相等运算符(!=)。<>运算符以及<=>=运算符也必须成对重载。

下面是一个运算符重载的示例,如代码清单6-10所示。我们为OperatorSample类重载了加(+)运算符,实现了可以使用加运算符来实现两个OperatorSample对象的相加功能,可见运算符重载很大程度上提高了编程的便利性。通过重载运算符,可以使用更熟悉或更自然的方式来操作两个自定义对象。

代码清单6-10 运算符重载示例

using System;

namespace ProgrammingCSharp4
{
    class OperatorSample
    {
        public int Value { get; set; }

        static void Main()
        {
            OperatorSample o1 = new OperatorSample();
            o1.Value = 10;
            OperatorSample o2 = new OperatorSample();
            o2.Value = 20;
            OperatorSample o3 = o1 + o2;
            Console.WriteLine(o3.Value);
        }

        public static OperatorSample operator +(OperatorSample o1, OperatorSample o2)
        {
            OperatorSample o = new OperatorSample();
            o.Value = o1.Value + o2.Value;
            return o;
        }
    }
}

上述代码的运行结果如下:

30

14.2 可重载的运算符

并非所有的运算符都可以重载,以下是可重载的运算符:

  1. 一元运算符+-!~++--truefalse

  2. 二元运算符+-*/%&|^<<>>==!=><>=<=

其他还有一些运算符,虽然不能重载,但有相应的替代方案,例如:条件逻辑运算符不能重载,但可使用能够重载的&|进行计算;数组索引运算符不能重载,但可定义索引器;转换运算符不能重载,但可定义新的转换运算符(使用explicitimplicit关键字)。

最后,我们再列出不能重载的运算符,如:=.? :newissizeoftypeof

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

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

相关文章

蓝桥杯 Python 组知识点容斥原理

容斥原理 这张图初中或者高中数学课应该画过 也就是通过这个简单的例子引出容斥原理的公式 这张图的面积&#xff1a;s1 s3 s7 - 2 * s2 - 2 * s4 - 2 * s6 3 * s5 通过此引导出容斥原理公式 那么下面来一起看看题目 题目描述 给定 n,m 请求出所有 n 位十进制整数中有多…

PDF文件提取开源工具调研总结

概述 PDF是一种日常工作中广泛使用的跨平台文档格式&#xff0c;常常包含丰富的内容&#xff1a;包括文本、图表、表格、公式、图像。在现代信息处理工作流中发挥了重要的作用&#xff0c;尤其是RAG项目中&#xff0c;通过将非结构化数据转化为结构化和可访问的信息&#xff0…

PDF编辑 PDF-XChange Editor Plus 免装优化版

PDF编辑器很多打工人都需要用到&#xff0c;也分享过好几款口碑不错的&#xff0c;这次这款PDF依旧值得你的期待。 PDF-XChange Editor&#xff0c;号称打开速度最快最强大的PDF编辑器/PDF阅读器&#xff0c;专注于PDF文档的编辑&#xff0c;可以自定义制作PDF电子文档&#xf…

IP属地会随着人的移动而改变吗

在当今数字化时代&#xff0c;互联网已成为人们生活中不可或缺的一部分。无论是社交媒体的日常互动&#xff0c;还是在线购物、远程工作&#xff0c;IP地址作为网络身份的重要标识&#xff0c;扮演着举足轻重的角色。随着移动互联网技术的飞速发展&#xff0c;人们越来越多地在…

我的世界-与门、或门、非门等基本门电路实现

一、红石比较器 (1) 红石比较器结构 红石比较器有前端单火把、后端双火把以及两个侧端 其中后端和侧端是输入信号,前端是输出信号 (2) 红石比较器的两种模式 比较模式 前端火把未点亮时处于比较模式 侧端>后端 → 0 当任一侧端强度大于后端强度时,输出…

【大数据】机器学习------支持向量机(SVM)

支持向量机的基本概念和数学公式&#xff1a; 1. 线性可分的支持向量机 对于线性可分的数据集 &#xff0c;其中(x_i \in R^d) 是特征向量 是类别标签&#xff0c;目标是找到一个超平面 &#xff0c;使得对于所有 的样本 &#xff0c;对于所有(y_i -1) 的样本&#xff0c;…

RDD和DataFrame两种数据结构的对比

文章目录 1. 实战概述2. RDD&#xff08;弹性分布式数据集&#xff09;2.1 RDD概念2.2 RDD特点2.3 实战操作 3. DataFrame&#xff08;数据帧&#xff09;3.1 DataFrame概念3.2 DataFrame优点3.3 实战操作 4. 实战小结 1. 实战概述 今天我们将深入探讨 Apache Spark 中的两种核…

中职网络建设与运维ansible服务

ansible服务 填写hosts指定主机范围和控制节点后创建一个脚本&#xff0c;可以利用简化脚本 1. 在linux1上安装系统自带的ansible-core,作为ansible控制节点,linux2-linux7作为ansible的受控节点 Linux1 Linux1-7 Yum install ansible-core -y Vi /etc/ansible/hosts 添加…

Kibana 控制台中提供语义、向量和混合搜索

作者&#xff1a;来自 Elastic Mark_Laney 想要将常规 Elasticsearch 查询与新的 AI 搜索功能结合起来吗&#xff1f;那么&#xff0c;你不需要连接到某个第三方的大型语言模型&#xff08;LLM&#xff09;吗&#xff1f;不。你可以使用 Elastic 的 ELSER 模型来改进现有搜索&a…

多种 Docker 镜像拉取解决方案与实践

最近国内 Docker 镜像拉取不太通畅&#xff0c;尝试了几种镜像拉取的方式&#xff0c;写篇博客分享一下。 原以为只是 docker hub 被毙了&#xff0c;上机器一操作&#xff0c;官方的下载地址也被毙了&#xff0c;真是从源头解决问题。 不过还好目前还有其他源能用&#xff0…

2025边缘计算新年沙龙成功举办,共话边缘AI未来

1月11日下午&#xff0c;北京市海淀区中关村创业大街热闹非凡&#xff0c;以“云边腾跃&#xff0c;蛇启新航”为主题的 2025边缘计算新年沙龙 盛大举行。本次活动汇聚了边缘计算、人工智能以及云边协同领域的顶尖专家、学者和从业者&#xff0c;共同探讨技术前沿与实际应用场景…

使用redis-cli命令实现redis crud操作

项目场景&#xff1a; 线上环境上redis中的key影响数据展示&#xff0c;需要删除。但环境特殊没办法通过 redis客户端工具直连。只能使用redis-cli命令来实现。 操作步骤&#xff1a; 1、确定redis安装的服务器&#xff1b; 2、找到redis的安装目录下 ##找到redis安装目…

CentOS 下载软件时报Error: Failed to synchronize cache for repo ‘AppStream‘解决方法

下载软件时出现以下问题 直接把CentOS-AppStream.repo改个名字就行 cd /etc/yum.repos.d/ mv CentOS-AppStream.repo CentOS-AppStream.repo.bak就可以了 解决思路 把AI问遍&#xff0c;无人会&#xff0c;解决法 想要下载软件通通失败了&#xff0c;解决方法当然是问AI&am…

【深度学习】神经网络之Softmax

Softmax 函数是神经网络中常用的一种激活函数&#xff0c;尤其在分类问题中广泛应用。它将一个实数向量转换为概率分布&#xff0c;使得每个输出值都位于 [0, 1] 之间&#xff0c;并且所有输出值的和为 1。这样&#xff0c;Softmax 可以用来表示各类别的预测概率。 Softmax 函…

python管理工具:conda部署+使用

python管理工具&#xff1a;conda部署使用 一、安装部署 1、 下载 - 官网下载&#xff1a; https://repo.anaconda.com/archive/index.html - wget方式&#xff1a; wget -c https://repo.anaconda.com/archive/Anaconda3-2023.03-1-Linux-x86_64.sh2、 安装 在conda文件的…

当PHP遇上区块链:一场奇妙的技术之旅

PHP 与区块链的邂逅 在技术的广袤宇宙中&#xff0c;区块链技术如同一颗耀眼的新星&#xff0c;以其去中心化、不可篡改、透明等特性&#xff0c;掀起了一场席卷全球的变革浪潮。众多开发者怀揣着对新技术的热忱与探索精神&#xff0c;纷纷投身于区块链开发的领域&#xff0c;试…

unity——Preject3——开始界面拼面板

目录 1.创建panel&#xff0c;去掉panel自带的image&#xff0c;自己加一个image&#xff0c;使用锚点分配好 2.锚点&#xff08;快捷键点击后 ALTShift&#xff09; 锚点是什么&#xff1f; 锚点的实际例子 例子1&#xff1a;固定在父容器的中心 例子2&#xff1a;对齐到…

PyTorch使用教程(6)一文讲清楚torch.nn和torch.nn.functional的区别

torch.nn 和 torch.nn.functional 在 PyTorch 中都是用于构建神经网络的重要组件&#xff0c;但它们在设计理念、使用方式和功能上存在一些显著的区别。以下是关于这两个模块的详细区别&#xff1a; 1. 继承方式与结构 torch.nn torch.nn 中的模块大多数是通过继承 torch.nn…

传统以太网问题与VLAN技术详解

传统以太网的问题 广播域&#xff1a;在网络中能接收同一广播信息的所有设备&#xff08;计算机、交换机&#xff09;等的集合 说明&#xff1a;在一个广播域内&#xff0c;当一个设备发送广播帧时&#xff0c;该域内的所有设备都能接收到这个广播帧。工作原理&#xff1a;在以…

OpenAI Whisper:语音识别技术的革新者—深入架构与参数

当下语音识别技术正以前所未有的速度发展&#xff0c;极大地推动了人机交互的便利性和效率。OpenAI的Whisper系统无疑是这一领域的佼佼者&#xff0c;它凭借其卓越的性能、广泛的适用性和创新的技术架构&#xff0c;正在重新定义语音转文本技术的规则。今天我们一起了解一下Whi…