栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

▩Dart-数字——Native&Web

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

▩Dart-数字——Native&Web

目录

一、数的表示二、行为上的差别

1. 精度2. 身份标识3. 类型和类型检测4. 位运算5. 字符串的表示 三、Native与Web差异,该怎么做?
Dart应用程序通常针对多个平台。例如,Flitter应用程序可能以iOS、Android和web为目标。代码可以是相同的,只要应用程序不依赖于特定于平台的库或以依赖于平台的方式使用数字。

本章详细介绍了Native number和Web number实现之间的差异,以及如何编写代码以使这些差异无关紧要。

Dart和其他语言中的数字实现
出于性能、代码大小和平台互操作性的考虑,Dart始终【允许】特定于平台的数字表示和语义。
类似地,在C/C++中,通常用于整数值的int类型是特定于平台的,以最好地映射到本地机器体系结构(16、32或64位)。在Java中,分数值的float和double类型最初被设计为在所有平台上严格遵循IEEE 754,但出于效率原因,这一约束几乎立即被放松(strictfp[Java关键字]是精确一致性所必需的)。

一、数的表示

在Dart中,所有数字都是公共对象类型层次结构的一部分,并且有两种具体的、用户可见的数字类型:int(表示整数值)和double(表示小数)。

根据平台的不同,这些数字类型具有不同的隐藏实现。特别是,Dart有两种非常不同的目标类型:

Native:通常是64位移动或桌面处理器。Web:Javascript作为主要执行引擎。

下表显示了Dart数字通常是如何实现的:

表示Native intNative doubleWeb intWeb double
64位有符号二进制补码
64位浮点

对于本机目标,可以假设int映射到有符号的64位整数表示,double映射到与底层处理器匹配的64位IEEE浮点表示。

但在web上,Dart编译到Javascript并与Javascript进行互操作,只有一个数字表示:64位双精度浮点值。为了提高效率,Dart将int和double映射到此单一表示形式。可见类型层次结构保持不变,但底层隐藏的实现类型不同且相互交织。

下图说明了本机和web目标的特定于平台的类型(蓝色)。如图所示,本机上int的具体类型只实现int接口。但是,web上int的具体类型同时实现int和double。

备忘: 为了提高效率,Dart以几种不同的方式表示int和double,但这些实现类(上面的蓝色部分)是隐藏的。通常,你可以忽略特定于平台的类型,将int和double视为具体类型。

web上的int表示为不含小数部分的双精度浮点值。在实践中,这非常有效:双精度浮点提供53位整数精度。但是,int值也总是double值,这可能会导致一些意外。

二、行为上的差别

大多数整数和双精度算术基本上具有相同的行为。但是,这里有一些重要的区别——特别是当你的代码对精度、字符串格式或底层运行时类型有严格要求时。

如本节所述,当算术结果不同时,行为是特定于平台的,可能会发生变化。

备忘: 本页描述的任何特定于平台的行为都可能会变得不那么令人惊讶、更加一致或更具性能。

1. 精度

下表说明了某些数值表达式因精度不同而存在的差异。在这里,math代表dart:math库,math.pow(2, 53)=253

在web上,整数的精度超过53位。特别是,由于截断,253和253+1映射到相同的值。在Native上,这些值仍然可以区分,因为本机数字有64位——63位表示值,1位表示符号。

当比较263-1和263时,溢出的影响是可见的。在本机上,后一个溢出到-263,这与二进制的补码算法一样。在web上,这些值不会溢出,因为它们的表示方式不同;由于精度损失,它们是近似值。

表达示NativeWeb
math.pow(2, 53) - 190071992547409919007199254740991
math.pow(2, 53)90071992547409929007199254740992
math.pow(2, 53) + 190071992547409939007199254740992
math.pow(2, 62)46116860184273879044611686018427388000
math.pow(2, 63) - 192233720368547758079223372036854776000
math.pow(2, 63)-92233720368547758089223372036854776000
math.pow(2, 64)018446744073709552000
2. 身份标识

在本机平台上,double和int是不同的类型:任何值都不能同时是double和int。在web上,这不是真的。由于这种差异,不同平台之间的身份可能不同。

下表显示了一些使用等式和标识的表达式。在本机和web上的等式表达式相同;身份表达通常是不同的。

表达示NativeWeb
1.0 == 1truetrue
identical(1.0, 1)falsetrue
0.0 == -0.0truetrue
identical(0.0, -0.0)falsetrue
double.nan == double.nanfalsefalse
identical(double.nan, double.nan)truefalse
double.infinity == double.infinitytruetrue
identical(double.infinity, double.infinity)truetrue
3. 类型和类型检测

在web上,基础int类型类似于double的子类型:它是一个不含小数部分的双精度值。事实上,如果x是一个带有零值小数部分的数字(双精度),那么形式为x is int的web类型检查返回true。

因此,网络上的以下情况是正确的:

所有Dart数字(num类型的值)均为双精度。Dart数字可以同时是double(又精度)和整数(int)。

这些事实会影响is检查和runtimeType属性。副作用是double.infinity被解释为int。因为这是特定于平台的行为,所以将来可能会发生变化。

表达示NativeWeb
1 is inttruetrue
1 is doublefalsetrue
1.0 is intfalsetrue
1.0 is doubletruetrue
(0.5 + 0.5) is intfalsetrue
(0.5 + 0.5) is doubletruetrue
3.14 is intfalsefalse
3.14 is doubletruetrue
double.infinity is intfalsetrue
double.nan is intfalsefalse
1.0.runtimeTypedoubleint
1.runtimeTypeintint
1.5.runtimeTypedoubledouble
4. 位运算

出于web上的性能原因,int上的按位(&、|、^、~)和移位(<<,>>,>>>)运算符使用本机Javascript等价物。在Javascript中,操作数被截断为32位整数,并被视为无符号整数。这种处理方法可以在更大的数量上产生令人惊讶的结果。特别是,如果操作数为负数或不适合32位,则它们可能在本机和web之间产生不同的结果。

下表显示了当操作数为负或接近32位时,本机和web平台如何处理按位运算符和移位运算符:

表达示NativeWeb
-1 >> 0-14294967295
-1 ^ 2-34294967293
math.pow(2, 32).toInt()42949672964294967296
math.pow(2, 32).toInt() >> 121474836480
(math.pow(2, 32).toInt()-1) >> 121474836472147483647
5. 字符串的表示

在web上,Dart通常使用Javascript将数字转换为字符串(例如,打印)。下表演示了转换第一列中的表达式如何导致不同的结果。

表达示Native toString()Web toString()
1“1”“1”
1.0“1.0”“1”
(0.5 + 0.5)“1.0”“1”
1.5“1.5”“1.5”
-0“0”“-0.0”
math.pow(2, 0)“1”“1”
math.pow(2, 80)“0”“1.2089258196146292e+24”
三、Native与Web差异,该怎么做?

通常,你不需要更改数字代码。Dart代码已经在本机和web平台上运行了多年,实现数量上的差异很少成为问题。常见的、典型的代码(例如遍历一系列小整数和索引列表)的行为也是一样的。

如果你有比较字符串结果的测试或断言,请以平台弹性的方式编写它们。例如,假设你正在测试嵌入数字的字符串表达式的值:

void main() {
	var count = 10.0 * 2;
	var message = "$count cows";
	if (message != "20.0 cows")
		throw Exception("Unexpected:$message");
}

前面的代码在本机平台上成功,但在web上抛出,因为web上的消息是“20 cows”(无小数)。或者,你可以按如下方式编写条件,以便在本机和web平台上传递:

if (message != "${20.0} cows") throw ...

对于位操作,考虑在32位块上显式操作,这些块在所有平台上都是一致的。要强制对32位块进行有符号解释,请使用int.toSigned(32)。

对于精度较高的其他情况,请考虑其他数值类型。BigInt类型在本机和web上都提供任意精度整数。fixnum包提供严格的64位有符号数字,即使在web上也是如此。不过,请谨慎使用这些类型:它们通常会导致代码变得更大、更慢。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/716739.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号