为啥我不能将数字转换为双精度数?
Posted
技术标签:
【中文标题】为啥我不能将数字转换为双精度数?【英文标题】:Why can't I convert a Number into a Double?为什么我不能将数字转换为双精度数? 【发布时间】:2018-12-23 00:41:07 【问题描述】:weight
是一个字段(Firestore中的数字),设置为100
。
int weight = json['weight'];
double weight = json['weight'];
int weight
工作正常,按预期返回 100
,但 double weight
崩溃(Object.noSuchMethod
异常)而不是返回 100.0
,这是我的预期。
但是,以下工作:
num weight = json['weight'];
num.toDouble();
【问题讨论】:
double weight = json['weight'].toDouble()
?
你可以这样做:double weight = json['weight'] + 0.0;
它是 Dart,而不是 Flutter 本身。 Dart 对打字非常严格。最终,它使代码更清晰。但需要一点时间来适应它——Dart 不会为你神奇地转换变量。
【参考方案1】:
从 Firestore 解析 100
时(实际上不支持“数字类型”,但 converts it),按照标准,它将被解析为 int
。Dart 不会自动“智能”地转换这些类型。实际上,您不能将int
转换为double
,这是您面临的问题。如果可能的话,你的代码就可以正常工作了。
解析
相反,您可以自己解析:
double weight = json['weight'].toDouble();
铸造
同样有效的方法是将 JSON 解析为 num
,然后将其分配给 double
,这会将 num
转换为 double
。
double weight = json['weight'] as num;
一开始这似乎有点奇怪,实际上Dart Analysis tool(例如内置于 VS Code 和 IntelliJ 的 Dart 插件中)会将其标记为 “不必要的演员表”,事实并非如此。
double a = 100; // this will not compile
double b = 100 as num; // this will compile, but is still marked as an "unnecessary cast"
double b = 100 as num
编译是因为 num
is the super class 的 double
和 Dart 将 super 转换为子类型,即使没有显式转换。显式演员表如下:
double a = 100 as double; // does not compile because int is not the super class of double
double b = (100 as num) as double; // compiles, you can also omit the double cast
Here is a nice read 关于“Dart 中的类型和转换”。
说明
发生在你身上的事情如下:
double weight;
weight = 100; // cannot compile because 100 is considered an int
// is the same as
weight = 100 as double; // which cannot work as I explained above
// Dart adds those casts automatically
【讨论】:
这大多是错误的。 Dart 永远不会为您将整数值转换为双精度值,您必须调用.toDouble()
。对数字执行 as
转换不会更改其类型。如果您在 VM 上运行 double x = 42 as num;
,您将收到运行时错误,因为整数不是双精度数。它在编译为 javascript 时可以工作,但这只是因为 JavaScript 中的所有数字实例都是双精度数,即使是 int
也是如此。
@lrn 它工作正常。我在发布之前对其进行了测试。您也可以查看我链接的内容。
我可能误读了您所写的内容,如果是这样,我深表歉意。我对您所说的工作内容感到非常困惑(.toDouble()
有效,其他所有内容在 VM 上运行时都无效,但从文本中不清楚它是不应该工作的示例)。 “解析”部分实际上是从 int 转换为 double,“转换”部分正在做的事情在运行时都失败了。所以,也许我只是说信息不明确。
不确定您指的是哪个链接,但我对 Dart 类型系统和运行时行为非常熟悉。我是从 Dart 2 静态和运行时类型系统的角度说的,但我在这里所说的也适用于 --checked
更多的 Dart 1(它检查类型而不是忽略它们并允许任何东西)。【参考方案2】:
你可以在一行中完成:
double weight = (json['weight'] as num).toDouble();
【讨论】:
【参考方案3】:您可以解析数据,如下所示:
这里的文档是Map<String,dynamic>
double opening = double.tryParse(document['opening'].toString());
【讨论】:
这可以作为评论安全地发表【参考方案4】:在 Dart 中,int
和 double
是不同的类型,都是 num
的子类型。
数字类型之间没有自动转换。如果你写:
num n = 100;
double d = n;
您将收到运行时错误。 Dart 的静态类型系统允许不安全的向下转换,因此 n
到 d
的不安全分配(不安全,因为并非所有 num
值都是 double
值)被隐式处理为:
num n = 100;
double d = n as double;
as double
检查该值实际上是double
(或null
),如果不是则抛出。如果该检查成功,则它可以安全地将值分配给d
,因为已知它与变量的类型匹配。
这就是这里发生的事情。 json['weight']
的实际值(可能是静态类型 Object
或 dynamic
)是值为 100 的 int
对象。将其分配给 int
有效。将其分配给num
有效。将其分配给double
throws。
如果数字没有小数或指数部分,Dart JSON 解析器会将其解析为整数(0.0
是双精度数,0e0
是双精度数,0
是整数)。这在大多数情况下非常方便,但在像您这样需要double
但创建 JSON 的代码并没有将其写为双精度的情况下偶尔会很烦人。
在这种情况下,您只需在提取值时在值上写上.toDouble()
。这是对实际双打的无操作。
附带说明一下,编译为 JavaScript 的 Dart 将所有数字表示为 JavaScript Number 类型,这意味着所有数字都是双精度数。在 JS 编译的代码中,所有的整数都可以被赋值为 double 而无需转换。当代码在非 JS 实现(如 Flutter、Dart VM/server 或 ios 的提前编译)上运行时,这将不起作用,所以不要依赖它,或者你的代码将不可移植。
【讨论】:
您没有收到运行时错误。我不明白你从哪里得到的。也许曾经是这种情况,但您可以在 VM 上尝试。既没有编译错误,也没有运行时错误。 刚试过:main() num n = 100; double d = n;
在 Dart 2 VM 上运行会得到Unhandled exception: type 'int' is not a subtype of type 'double'
。添加as double
没有区别。该分配曾经在 unchecked Dart 1 代码中工作,但如果您在运行 Dart 1 时使用--checked
,它将以完全相同的方式失败。 int
不是 double
。 (同样,当编译成 JavaScript 时,整数实际上也是双精度数,因为 JavaScript 只有一种数字类型)。【参考方案5】:
像这样简单地将int
转换为double
int a = 10;
double b = a + 0.0;
【讨论】:
为什么要投反对票?我已经测试了这个解决方案它工作正常。如果您有带有 int 数据的动态列表,那么类型转换也会失败,那么只有这个解决方案有效。请尝试一次否决票。以上是关于为啥我不能将数字转换为双精度数?的主要内容,如果未能解决你的问题,请参考以下文章