为啥我不能将数字转换为双精度数?

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),按照标准,它将被解析为 intDart 不会自动“智能”地转换这些类型。实际上,您不能将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 中,intdouble 是不同的类型,都是 num 的子类型。

数字类型之间没有自动转换。如果你写:

num n = 100;
double d = n;

您将收到运行时错误。 Dart 的静态类型系统允许不安全的向下转换,因此 nd 的不安全分配(不安全,因为并非所有 num 值都是 double 值)被隐式处理为:

num n = 100;
double d = n as double;

as double 检查该值实际上是double(或null),如果不是则抛出。如果该检查成功,则它可以安全地将值分配给d,因为已知它与变量的类型匹配。

这就是这里发生的事情。 json['weight'] 的实际值(可能是静态类型 Objectdynamic)是值为 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 数据的动态列表,那么类型转换也会失败,那么只有这个解决方案有效。请尝试一次否决票。

以上是关于为啥我不能将数字转换为双精度数?的主要内容,如果未能解决你的问题,请参考以下文章

在java中将十六进制数字字符串转换为双精度数字

译将字符转换为双精度浮点型

[C/C++笔面试]不使用库函数将字符串转换为整数

C#将数字四舍五入为双精度数的任意数字[重复]

C++ 将字符串转换为双精度

c语言,用循环的方法将字符串“123”转化成数字123,应该怎样写?