double.infinity和double.maxFinite在Dart中有什么区别?
在Flutter中,它们看起来都是做同样的事情。在Flutter中应该如何使用它们?
从一个严格的数据导向角度来看,区别在于 double.maxFinite
表示 double
数据类型可以包含的最大允许值,而 double.infinity
则表示无穷大。由于Dart在所有平台上都将 double
严格定义为64位浮点数,因此 double.maxFinite
的值被确定为 1.7976931348623157e+308
。(具体原因可能相当技术性,但jpopesculian的答案部分涉及了一些内容,总体来说,对于简单的应用程序开发,理解这些细节通常并不是必需的。)
在Flutter中,大多数情况下,这两个值之间没有太大的实际差异。你通常会在调整小部件大小时使用这些常量,并且当你希望小部件尽可能大时,你可以将宽度和/或高度设置为 double.infinity
:
SizedBox(
width: 500,
height: 500,
child: Container(
width: double.infinity,
height: double.infinity,
),
)
Container
被赋予了无限的宽度和高度。Flutter会通过使用其父级来确定实际可用空间并对其进行约束来计算其大小。在这种情况下,Container
受到SizedBox
的限制,SizedBox
对Container
施加了500像素乘以500像素的硬限制 - 无论Container
请求多少空间,它都不能超过这个大小。因此,将double.infinity
替换为double.maxFinite
不会改变任何东西,因为父级SizedBox
仍然只允许它变得如此大。MaterialApp
或Scaffold
的东西,将其子级约束为屏幕的大小)。因此,大多数情况下,试图比可用空间更大的子级不会成为太大的问题,因为Flutter的布局规则足够强大,可以防止它们占用超过允许的空间。Column(
children: [
Container(
height: double.infinite,
),
],
)
Column
。作为它的子元素,它有一个请求无限高度的Container
。问题很明显:Flutter如何将一个无限高的小部件约束在具有无限约束的父部件中?确实如此,尝试渲染此小部件会产生以下错误:════════ Exception caught by rendering library ═════════════════════════════════
The following assertion was thrown during performLayout():
BoxConstraints forces an infinite height.
所以,如果问题是无限大小的小部件无法存在于无限约束的空间中,那么如果我们将 double.infinity
更改为 double.maxFinite
在 Container
中会怎么样?这将解决问题,因为 Container
不再是无限大小的,Flutter 可以正常计算其约束:
Column(
children: [
Container(
height: double.maxFinite,
color: Colors.red,
),
],
)
成功!无限高度约束错误已经消失!
...我们只是得到了这个错误:
════════ Exception caught by rendering library ═════════════════════════════════
The following assertion was thrown during layout:
A RenderFlex overflowed by 1.7976931348623157e+308 pixels on the bottom.
所以,尽管现在高度被正确计算了,Column
如果其子项的高度超过可用空间,将会出现问题。事实证明,对于现代屏幕来说,大约一百个百亿像素太高了。[需要引用]
(对于那些好奇的人来说,这里的解决方案是将Container
包装在Expanded
中,它将占据Column
中的可见空间,并再次强制执行有限约束,限制Container
不超过允许的空间。[或者,你知道的,你也可以不创建如此庞大的小部件。])
总之,在使用Flutter中的double.infinity
的地方,通常double.infinity
和double.maxFinite
之间没有实际区别。但在偶尔有区别的情况下,你通常只会把一个问题换成另一个问题。
double
)的存储方式。(免责声明:我将使用16位来解释,忽略字节序,但实际上Dart将根据平台使用32位或64位。)int
)的存储方式如下: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
| |___________________________________________|
| |
v v
sign bit magnitude
第0位是符号(0表示正数,1表示负数),其余位是幅值,例如实际数字。因此,-142看起来像1000000010001110
相比之下,浮点数(double
)的存储方式如下:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
| |__________||_______________________________|
| | |
v v v
sign bit exponent fraction
第0位是符号位,接下来的4位是指数,最后的位数是小数部分。表示的公式如下:
n = (sign) * 2^(exponent - 7) * (1 + fraction)
其中分数是2的倒数幂之和。例如,0100001100000000
表示
sign = 1 // positive because byte 0 is 0
exponent = 8 // 1000 as a decimal
fraction = 0.375 // 0*2^-1 + 1*2^-2 + 1*2^-3 + 0*2^-4 + 0*2^-5 ...
n = 2.75 // 1 * 2^(8-7) * (1 + 0.375)
此外,该标准将允许在给定某些指数的情况下表示特殊值。
使用指数0000
,我们可以表示更小的数字“次正常”数字。
n = (sign) * 2^-6 * (0 + fraction)
指数为1111
时,如果小数部分为零,则可以表示正无穷或负无穷。例如,0111100000000000
表示正无穷。如果小数部分不为零,则变成NaN或非数字。
因此,回答您的问题,double.infinity
表示0111100000000000
,double.maxFinite
表示0011111111111111
。这也可能有助于解释其他常量,如double.nan
或double.minPositive
,它表示0000000000000001
区别可以概括为:
一些小部件允许它们的子元素尽可能大
Column
、ListView
、OverflowBox
在这种情况下使用double.infinity
根据文档,这些是分配给各种double
常量的值。
static const double infinity = 1.0 / 0.0;
static const double negativeInfinity = -infinity;
static const double minPositive = 5e-324;
static const double maxFinite = 1.7976931348623157e+308;
希望这回答了你的问题
double.maxFinite
可用的情况,在两种情况下都使用了 double.infinity
。 - iDecode
double.infinity
代表着无穷大。double.maxFinite
代表着一个double
可以存储的最大值,但它 不是 无穷大。 - jamesdlin