[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

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

参考

相关文章
|
2月前
|
Dart
如何在 Flutter 项目中使用 Dart 语言?
如何在 Flutter 项目中使用 Dart 语言?
127 58
|
20天前
|
Dart
flutter dart mixin 姿势
flutter dart mixin 姿势
|
1月前
|
Dart 开发者 Windows
flutter:dart的学习
本文介绍了Dart语言的下载方法及基本使用,包括在Windows系统上和VSCode中的安装步骤,并展示了如何运行Dart代码。此外,还详细说明了Dart的基础语法、构造函数、泛型以及库的使用方法。文中通过示例代码解释了闭包、运算符等概念,并介绍了Dart的新特性如非空断言操作符和延迟初始化变量。最后,提供了添加第三方库依赖的方法。
29 12
|
1月前
|
开发框架 移动开发 Android开发
安卓与iOS开发中的跨平台解决方案:Flutter入门
【9月更文挑战第30天】在移动应用开发的广阔舞台上,安卓和iOS两大操作系统各自占据半壁江山。开发者们常常面临着选择:是专注于单一平台深耕细作,还是寻找一种能够横跨两大系统的开发方案?Flutter,作为一种新兴的跨平台UI工具包,正以其现代、响应式的特点赢得开发者的青睐。本文将带你一探究竟,从Flutter的基础概念到实战应用,深入浅出地介绍这一技术的魅力所在。
76 7
|
3月前
|
Dart 前端开发 JavaScript
Flutter&Dart-异步编程Future、Stream极速入门
Flutter&Dart-异步编程Future、Stream极速入门
76 4
Flutter&Dart-异步编程Future、Stream极速入门
|
3月前
|
Dart JavaScript 前端开发
Dart或Flutter中解决异常-type ‘int‘ is not a subtype of type ‘double‘
Dart或Flutter中解决异常-type ‘int‘ is not a subtype of type ‘double‘
133 4
|
3月前
|
Kubernetes Cloud Native 搜索推荐
探索云原生技术:Kubernetes入门与实践打造个性化安卓应用:从零开始的Flutter之旅
【8月更文挑战第31天】云原生技术正改变着应用开发和部署的方式。本文将带你了解云原生的基石——Kubernetes,通过实际的代码示例,从安装到部署一个简单的应用,让你迅速掌握Kubernetes的核心概念和操作方法。无论你是初学者还是有一定经验的开发者,这篇文章都将成为你进入云原生世界的桥梁。
|
3月前
|
Dart 开发工具
消除Flutter doctor的警告Warning: `dart` on your path resolves to xxx/bin/dart
消除Flutter doctor的警告Warning: `dart` on your path resolves to xxx/bin/dart
67 0
|
存储 缓存 Dart
[Flutter]足够入门的Dart语言系列之面向对象:类成员的可见性、常量和工厂构造函数详解
类和成员的可见性,这在基于库或包的开发中非常重要,Dart中提供了工厂构造函数,可以方便的实现单例、缓存实例对象、返回子类等,以及常量构造函数的使用......
300 0
[Flutter]足够入门的Dart语言系列之面向对象:类成员的可见性、常量和工厂构造函数详解
|
6月前
|
前端开发 C++ 容器
Flutter-完整开发实战详解(一、Dart-语言和-Flutter-基础)(1)
Flutter-完整开发实战详解(一、Dart-语言和-Flutter-基础)(1)