Qt QML 中疯狂字符串数字比较的解决方法

Posted

技术标签:

【中文标题】Qt QML 中疯狂字符串数字比较的解决方法【英文标题】:Workaround for crazy string numeric comparison in Qt QML 【发布时间】:2016-11-01 10:05:27 【问题描述】:

这是 Qt (LTS 5.6.2) QML javascript 实现中的疯狂字符串到数字比较:

console.log("240000000000" == "3776798720");
console.log("240000000000" === "3776798720");
console.log("240000000000" === "3776798721");

输出是:

true
true
false

看起来字符串被解释为 (u)int32 并且高字节丢失:

240000000000 == 0x37E11D6000
3776798720   ==   0xE11D6000

此错误也会影响对象:

var g = ;
var h = "240000000000";
g[h] = h + "BUG";
console.log(JSON.stringify(g, null, 2));
console.log(g["3776798720"], g["240000000000"]);

输出:

qml: 
    "3776798720": "240000000000BUG"

qml: 240000000000BUG 240000000000BUG

如您所见,钥匙已损坏。该值可以通过两个不同的字符串获取。

问题

是否有任何选项可以在不修补 Qt 的情况下解决此问题?或者至少是 Qt 中提高自己的问题的大概位置?

附言这里还有我同事报告的QTBUG-56830。

【问题讨论】:

如果环境变量`QV4_FORCE_INTERPRETER'设置为1,是否也会发生这种情况? 这是一个错误,还是 ecmascript 标准规定的? @peppe 不影响结果。 Kuba Ober 我查看了 ecmascript 5.1 并找不到类似的东西。看起来像一个 Qt 错误。并且不清楚在什么地方。 @KubaOber ECMA 声明属性名称应始终为字符串,当您通过字符串文字以外的其他方式访问属性时,应使用 ToString() 方法获取字符串值。 (11.2.1 , 11.1.5) 【参考方案1】:

我看不到解决方法,所以我做了一个修复:将我在此处发布的补丁应用到 qtdeclarative

https://codereview.qt-project.org/#/c/175782

然后重新编译。

【讨论】:

【参考方案2】:

这是似乎有效的解决方法

console.log(String("3776798720").localeCompare("240000000000") === 0)
console.log(String("3776798721").localeCompare("240000000000") === 0)
console.log(String("240000000000").localeCompare("240000000000") === 0)

输出:

qml: false
qml: false
qml: true

或者如果你有字符串变量

var str = "3776798720"
console.log(str.localeCompare("240000000000") === 0)

【讨论】:

doc 这个错误不仅仅是比较。对象的关键案例是最关键的。并且不能用 localeCompare 修复。 @misterion 是的,但你问是否有字符串数字比较的解决方法,所以我提供了一个答案。对于对象,除了从 C++ 注册您自己的 QML 类型(例如公开QJsonObject 接口)来解决问题外,我没有看到解决方法。对于内置对象,正如您所指出的,数字字符串被转换为int,我认为这是不正确的,确实是一个错误。

以上是关于Qt QML 中疯狂字符串数字比较的解决方法的主要内容,如果未能解决你的问题,请参考以下文章

Qt Quick QML 实例之疯狂数字游戏(QML C++混合编程翻译QSetting )建议收藏

Qt Quick QML 实例之疯狂数字游戏(QML C++混合编程翻译QSetting )建议收藏

如何在 Qt Creator 中解决“找不到 QML 模块”

Qt5在程序打包发布时遇到的问题和解决方法

QML MediaPlayer ServiceMissing异常解决办法

QT怎么解决不同分辨率