[Flutter]足够入门的Dart语言系列之常见运算符或操作符

简介: Dart中的运算符提供对数据操作和处理的能力,其中的算术运算符、逻辑运算符非常符合现实中的使用情况,其他不同的运算符则有着自己的操作逻辑...
Operator运算符,通常也称为“操作符”。

Dart中的运算符提供对数据操作和处理的能力,其中的算术运算符、逻辑运算符非常符合现实中的使用情况,其他不同的运算符则有着自己的操作逻辑。

下面是Dart中运算符描述【可先做了解】,其前后顺序表示了优先级(即多个操作符使用时,优先计算的顺序,使用()可以改变优先级)

描述 运算符
一元后缀 表达式++ 表达式-- () [] . ?. !
一元前缀 -表达式 !表达式 ~表达式 ++表达式 --表达式
乘除法 * / % ~/
加减法 + -
位运算 << >> >>>
二进制与 &
二进制异或 ^
二进制或 ` `
关系和类型测试 >= > <= < as is is!
相等判断 == !=
逻辑与 &&
逻辑或 ` `
空判断 ??
条件表达式 _表达式 1_ ? _表达式 2_ : _表达式 3_
级联 .. ?..
赋值 = *= /= += -= &= ^= 等等……

算术运算符(Arithmetic operators

算术运算

算术运算是最基础的数值计算,包括:

  • + Add
  • - Subtract
  • -expr 减去,也称为负 (表达式的符号反转)
  • * Multiply
  • / Divide 返回double类型的相除的结果。
  • ~/ 返回相除的整数,即取商,大多数编程语言/会返回结果的整数。
  • % 取余(或取模),返回两个数相除的余数。

如下,算术运算符的使用:

int a = 10;
int b = 3;
print(a + b); // 13
print(a - b); // 7
print(a * b); // 30
print(a / b); // 3.3333333333333335
print(a ~/ b); // 3
print(a % b); // 1

精度问题

对于浮点数来说,会有精度损失的问题,通常按需要能满足精度要求即可(比如小数后几位)。

double a = 10.6;
double b = 3.3;
print(a + b); // 13.899999999999999
print(a - b); // 7.3
print(a * b); // 34.98
print(a / b); // 3.2121212121212124
print(a ~/ b); //3
print(a % b); // 0.7000000000000002

身高、体重、长度等一般保留两三位小数即可。对于金融场景下,需要非常高精度计算的时候,推荐使用decimal第三方库。

条件运算符(比较运算符,或Equality and relational operators

比较运算符用于比较变量,其结果返回一个bool值。

  • == 相等
  • `!= 不等
  • > 大于
  • < 小于
  • >= 大于等于
  • <= 小于等于

如下,变量a、b比较运算:

int a = 5;
int b = 6;
print(a > b); // false
print(a < b); // true
print(a == b); // false
print(a != b); // true
print(a >= b); // false
print(a <= b); // true

逻辑运算符(Logical operators

逻辑运算是对bool(真、假)的运算。有与-&&或-||非-!三种。

  • && —— 与运算,当两边都为true时,结果才为true。表示的是并且/同时
  • || —— 或运算,当两边有一个为true时,结果就为true。表示的是或者/满足其中一个
  • ! —— 非或取反运算,对表达式的bool值取反。表示的是不是/

比如,对于游乐场的要求:

身高小于1.4,并且年龄小于16才能游玩,则可以如下表示:

int age = 16;
double height = 1.3;
if(age<16 && height<1.4){
    print("允许游玩");
}
else{
  print("不允许游玩");
}

// 不允许游玩

身高小于1.4,或年龄小于16才能游玩,则可以如下表示:

int age = 16;
double height = 1.3;
if(age<16 || height<1.4){
    print("允许游玩");
}
else{
  print("不允许游玩");
}

// 允许游玩

身高大于1.4或年龄大于16,不满足这个条件的就能游玩,则可以如下表示:

int age = 16;
double height = 1.3;
if (!(age > 16 || height > 1.4)) {
  print("允许游玩");
} else {
  print("不允许游玩");
}

// 允许游玩
逻辑运算符的“短路”特点:

&&||两元逻辑运算符在计算时,如果左侧的表达式就能确定逻辑结果时,则不会对右侧的表达式进行取值计算。

&&左侧为false,结果必然为false(一假全假);||左侧为true,结果必然为true(一真全真)。由于短路策略,则不会进行右侧表达式多余的计算。

位运算符(Bitwise and shift operators

位运算针对的是计算机中的二进制位进行的运算,它是计算机中一切数据运算的本质(逻辑运算、算术运算、比较运算等都要转换为位运算)。

位运算符包括:

  • & 按位与
  • | 按位或
  • ^ 按位异或
  • ~expr 按位取反(即将 “0” 变为 “1”,“1” 变为 “0”)
  • << 位左移
  • >> 位右移
  • >>> 无符号右移
final value = 0x22;
final bitmask = 0x0f;

assert((value & bitmask) == 0x02); // AND
assert((value & ~bitmask) == 0x20); // AND NOT
assert((value | bitmask) == 0x2f); // OR
assert((value ^ bitmask) == 0x2d); // XOR
assert((value << 4) == 0x220); // Shift left
assert((value >> 4) == 0x02); // Shift right
assert((value >>> 4) == 0x02); // Unsigned shift right
assert((-value >> 4) == -0x03); // Shift right
assert((-value >>> 4) > 0); // Unsigned shift right

体会下按位计算的特点:

int类型在内存中占据 4 字节,每字节(byte)由 8 个二进制位(bit)表示。

65 、11 在计算机中以 32 个二进制位来记录:

十进制: 65
二进制: 0000 0000 0000 0000 0000 0000 0100 0001

十进制: 11
二进制: 0000 0000 0000 0000 0000 0000 0000 1011
  • &按位与
int a = 65;
int b = 11;
int c = a & b;

  0000 0000 0000 0000 0000 0000 0100 0001     a = 65
& 0000 0000 0000 0000 0000 0000 0000 1011     b = 11
  0000 0000 0000 0000 0000 0000 0000 0001     c = 1
  • |按位或
int a = 65;
int b = 11;
int c = a | b;

  0000 0000 0000 0000 0000 0000 0100 0001     a = 65
| 0000 0000 0000 0000 0000 0000 0000 1011     b = 11
  0000 0000 0000 0000 0000 0000 0100 1011     c = 75
  • ~按位取反
int b = 11;
int c = ~b;
  0000 0000 0000 0000 0000 0000 0000 1011  b = 11
~ 1111 1111 1111 1111 1111 1111 1111 0100  c = -12

print(c);   // -12
print(~c);  // 11

1111 1111 1111 1111 1111 1111 1111 0100作为机器码,最高位表示符号位,计算机将数据存储为补码的形式,也就是,-12的补码为1111 1111 1111 1111 1111 1111 1111 0100

如果是无符号整数,则其取值将为4294967284

原码是符号位和真值的绝对值,比如 -12 的原码表示:最高位为符号位,后面为其真值的绝对值。

-12 原码:  1000 0000 0000 0000 0000 0000 0000 1100

正数的反码是其本身;负数的反码是在其原码的基础上, 符号位不变,其余各个位取反:

-12 原码:  1000 0000 0000 0000 0000 0000 0000 1100
-12 反码:  1111 1111 1111 1111 1111 1111 1111 0011

正数的补码也是其本身;负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即反码+1)

-12 原码:  1000 0000 0000 0000 0000 0000 0000 1100
-12 反码:  1111 1111 1111 1111 1111 1111 1111 0011
-12 补码:  1111 1111 1111 1111 1111 1111 1111 0100

这就是上面取值为-12的原因。

  • ^按位异或
int a = 65;
int b = 11;
int c = a ^ b;

  0000 0000 0000 0000 0000 0000 0100 0001     a = 65
^ 0000 0000 0000 0000 0000 0000 0000 1011     b = 11
  0000 0000 0000 0000 0000 0000 0100 1010     c = 74
  • <<>>按位进行左移和右移
int a = 65;
int c = a << 2;

0000 0000 0000 0000 0000 0000 0100 0001     a = 65
0000 0000 0000 0000 0000 0001 0000 0100        c = 260

赋值运算符(Assignment operators

赋值运算符用于将一个值赋值给变量。使用的是=等于号,左侧为变量,右侧为可以获取的值(字面量、变量、表达式、函数等)。

  • =用于直接赋值。
  • ??=用于为值为null的变量赋值。
int a = 10;
int b = a + 40;

??=当变量为null时,才会进行赋值,是对null判断并赋值的一种语法糖(简写形式)。

int? a;


a??=10;

// 等价于
if(a==null){
    a=10;
}

=??=的同时使用:

int b = a ??= 20;
  • 组合赋值运算符

算数运算符、位运算符可以和赋值运算符进行组合,本质是两种运算符的简写。

比如 +=

int a = 10;
a += 20;

// 等同 a = a + 20;

此外还有:+= -= *= /= %= ~/= &= |= ^= <<= >>= >>>=

目前没有 ~=

--++自增自减运算符

自增自减运算符分为前置和后置两种类型。前置自增/自减是先进行自增/自减运算然后再取值;后置自增/自减是先取值然后再进行自增/自减。

var a = 10;
var b = 15;

var c = a++;
var d = b--;

var e = ++a;
var f = --b;

print('a=$a');
print('b=$b');
print('c=$c');
print('d=$d');
print('e=$e');
print('f=$f');

输出结果如下,可以对比了解前置自增/自减、后置自增/自减的区别:

a=12
b=13
c=10
d=15
e=12
f=13

条件表达式(Conditional expressions

条件表达式可以用来替代if-else语句,使条件处理更加简明。

condition?expr1:expr2 如果条件为真,执行 表达式1 并返回结果,否则执行 表达式2 并返回结果。

expr1 ?? expr2 如果 表达式1 不为 null 则返回其值,否则执行 表达式2 并返回其值。

如下,根据布尔表达式确定取值:

var visibility = isPublic ? 'public' : 'private';

根据是否为null确定取值:

var result = name ?? 'Guest';

??可以用?:三元表达式来实现:

var result = name!=null?name:'Guest';
?:有三个表达式,因此也被称为三元运算符,或三目运算符。

上面介绍的其他运算符,比如+-*/等有两个表达式,被称为二元或二目运算符;!~++等有一个表达式,被称为一元或单目运算符。

类型判断运算符(Type test operators)

as、is、is! 运算符用于在运行时判断对象的类型。

  • as 类型转换
  • is 如果对象是指定类型则返回 true
  • is! 如果对象是指定类型则返回 false

后续在对象的使用中进一步了解。

参考

相关文章
|
3月前
|
监控 Dart 安全
创建一个Dart应用,监控局域网上网记录的软件:Flutter框架的应用
在当今数字时代,网络安全变得愈发重要。为了监控局域网上的上网记录,我们可以借助Flutter框架创建一个强大的Dart应用。在这篇文章中,我们将深入讨论如何使用Flutter框架开发这样一个监控局域网上网记录的软件,并提供一些实用的代码示例。
276 1
|
2月前
|
Dart JavaScript
Flutter - Dart 基础(数据类型)
【2月更文挑战第3天】
66 1
|
2月前
|
Dart JavaScript 安全
|
2月前
|
Dart Shell 开发工具
解决windows安装Flutter时出现Unknown operating system. Cannot install Dart SDK.问题
解决windows安装Flutter时出现Unknown operating system. Cannot install Dart SDK.问题
|
3月前
|
JSON Dart 算法
Dart/Flutter工具模块:the_utils
Dart/Flutter工具模块:the_utils
47 0
|
3月前
|
Dart 小程序 前端开发
WebSocket 解析与应用(包含web前端、服务端、小程序、dart/flutter中的用法)
WebSocket 解析与应用(包含web前端、服务端、小程序、dart/flutter中的用法)
197 0
|
4月前
|
Dart 开发者
Flutter入门之Dart中的并发编程、异步和事件驱动详解
Flutter入门之Dart中的并发编程、异步和事件驱动详解 Dart是一种高效、快速、灵活且用于Web和移动应用程序开发的编程语言。在Dart中,支持并发编程、异步和事件驱动等特性,这些特性使得Dart在处理诸如网络请求、文件I/O、用户输入等方面表现出色。本文将详细介绍Dart中的这些特性。
|
5月前
|
Dart
通义灵码请问啥时候支持flutter或dart
通义灵码请问啥时候支持flutter或dart
264 1
|
6月前
|
Dart API Android开发
带你读《深入浅出Dart》二十二、Flutter简介
带你读《深入浅出Dart》二十二、Flutter简介
|
6月前
|
Dart 开发工具 iOS开发
带你读《深入浅出Dart》二十三、Flutter环境的安装与配置(1)
带你读《深入浅出Dart》二十三、Flutter环境的安装与配置(1)