gpt4 book ai didi

Groovy 原始 double 算术

转载 作者:行者123 更新时间:2023-12-02 09:51:09 28 4
gpt4 key购买 nike

结果是 127

double middle = 255 / 2

虽然这产生了 127.5

Double middle = 255 / 2

同时这也会产生 127.5

double middle = (255 / 2) as double

我知道 Groovy 默认使用 BigDecimal 进行操作,但对我来说这是一个巨大的错误!怎么会这样?

最佳答案

这实际上与 BigDecimals 无关,而是与从原始整数到原始 double 类型的强制转换有关。此问题是由 Groovy 编译器及其生成的(很可能)不正确的字节码引起的。看一下第一种情况的以下字节码表示。以下 Groovy 代码:

void ex1() {
double x = 255 / 2
println x
}

被编译为字节码,可以表示为:

public void ex1() {
CallSite[] var1 = $getCallSiteArray();
double x = 0.0D;
if (BytecodeInterface8.isOrigInt() && BytecodeInterface8.isOrigD() && !__$stMC && !BytecodeInterface8.disabledStandardMetaClass()) {
int var5 = 255 / 2;
x = (double)var5;
} else {
Object var4 = var1[5].call(255, 2);
x = DefaultTypeTransformation.doubleUnbox(var4);
}

var1[6].callCurrent(this, x);
}

这表明在这种情况下,不可能得到127.5作为结果,因为255/2表达式的结果存储在类型变量中int。感觉这是一个不一致行为的示例,因为使用 Double 的方法的字节码如下所示:

public void ex2() {
CallSite[] var1 = $getCallSiteArray();
Double x = null;
if (BytecodeInterface8.isOrigInt() && !__$stMC && !BytecodeInterface8.disabledStandardMetaClass()) {
Object var4 = var1[8].call(255, 2);
x = (Double)ScriptBytecodeAdapter.castToType(var4, Double.class);
} else {
Object var3 = var1[7].call(255, 2);
x = (Double)ScriptBytecodeAdapter.castToType(var3, Double.class);
}

var1[9].callCurrent(this, x);
}

此用例的主要问题是添加 @TypeChecked 并不能防止您犯此错误 - 编译通过并返回不正确的结果。但是,当我们将 @TypeChecked 注解添加到使用 Double 的方法时,会引发编译错误。添加 @CompileStatic 解决了问题。

我已经运行了一些测试,可以确认最近的 2.5.6 以及 3.0.0-alpha-4 版本中存在此问题。 I've created a bug report在 Groovy JIRA 项目中。感谢您发现并报告问题!

更新:Java 也做同样的事情

这似乎不是 Groovy 的错误 - Java 也是这样做的。在 Java 中,您可以将两个 int 相除的结果存储在 double 变量中,但除了将整数强制转换为 double 之外,您什么也得不到。对于 {{Double}} 类型,在语法方面有所不同,但在字节码方面非常相似。对于 {{Double}},您需要将方程的至少一部分显式转换为 {{double}} 类型,这会生成将两个整数转换为 {{double}} 的字节码。考虑以下 Java 示例:

final class IntDivEx {

static double div(int a, int b) {
return a / b;
}

static Double div2(int a, int b) {
return a / (double) b;
}

public static void main(String[] args) {
System.out.println(div(255,2));
System.out.println(div2(255,2));
}
}

当你运行它时,你会得到:

127.0
127.5

现在,如果您查看它创建的字节码,您将看到如下内容:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

final class IntDivEx {
IntDivEx() {
}

static double div(int a, int b) {
return (double)(a / b);
}

static Double div2(int a, int b) {
return (double)a / (double)b;
}

public static void main(String[] args) {
System.out.println(div(255, 2));
System.out.println(div2(255, 2));
}
}

Groovy 和 Java 之间的唯一区别(就语法而言)是 Groovy 允许您将整数隐式转换为 Double,这就是为什么

Double x = 255 / 2

在 Groovy 中是正确的语句,而在本例中,Java 在编译过程中失败并出现以下错误:

Error:(10, 18) java: incompatible types: int cannot be converted to java.lang.Double

这就是为什么在 Java 中,当您从整数分配到 Double 时需要使用强制转换。

关于Groovy 原始 double 算术,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55789411/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com