gpt4 book ai didi

java - 如何禁用 Java 中的转化和促销?

转载 作者:行者123 更新时间:2023-11-30 09:04:48 25 4
gpt4 key购买 nike

好的。我认为这是不可能的。如果您认为相同,则无需发布答案。我读了几行 Chapter 5. Conversions and Promotions并且第 5 章似乎没有提到在 Java 中禁用转换和提升。

这是我的动机:

long uADD(long a, long b) {
try {
long c;
c = 0;
boolean carry; //carry flag; true: need to carry; false: no need to carry
carry = false;
for (int i = 0; i < 64; ++i) { //i loops from 0 to 63,
if (((((a >>> i) & 1) ^ ((b >>> i)) & 1) != 0) ^ carry) { //calculate the ith digit of the sum
c += (1 << i);
}
if (((((a >>> i) & 1) & ((b >>> i) & 1)) != 0) || (carry && ((((a >>> i) & 1) ^ ((b >>> i) & 1)) != 0))) {
carry = true; //calculate the carry flag which will be used for calculation of the (i+1)th digit
} else {
carry = false;
}
}
if (carry) { //check if there is a last carry flag
throw new ArithmeticException(); //throw arithmetic exception if true
}
return c;
} catch (ArithmeticException arithmExcep) {
throw new ArithmeticException("Unsigned Long integer Overflow during Addition");
}
}

所以基本上,我正在编写一个方法来对长整数进行无符号加法。如果溢出会抛出算术异常。上面的代码可读性不够,所以我应该尝试解释一下。

首先,有一个for循环在哪里 i来自 0 的循环至 63 .

然后,第一个if语句作为全加器的总和输出,它使用i a 的第 1 位数字和b的和 carry标志来计算 i + 1第一位数字( truefalse )。 (注意 i = 0 对应个位数。)如果 true , 它增加了 1 << ic , 其中c最初是 0 .

在那之后,第二个if语句作为全加器的进位标志输出,它再次使用i a 的第 1 位数字和b的和 carry标志来计算 carry i + 1 的标志第 位数。如果true , 设置新的 carry标记为 true , 如果 false , 设置新的 carry旗帜 false .

最后,在退出 for 之后循环,检查是否 carry标志是 true .如果true , 抛出算术异常。

但是,上面的代码不起作用。调试后发现问题出在

c += (1 << i);

正确的代码应该是:

c += (1L << i);

因为Java会自动提升整数1 << i到 Long 并将其添加到 c ,没有向我显示任何警告。

我对此有几个问题。

  1. 是否可以禁止将一种数据类型自动提升为另一种数据类型
  2. 自动促销给您带来问题的频率如何?
  3. 是否可以调整 IDE,使其在发生自动升级时向我显示警告? (我目前使用的是 NetBeans IDE 7.3.1。)

对于很多问题和难以阅读的代码,我们深表歉意。我将在 9 月份学习 CS,所以我尝试用 Java 编写一些代码来熟悉 Java。

最佳答案

Is it possible to disable automatic promotion of one data type to another

否:因为您已经发现 Java 语言规范要求进行数字提升,任何执行此操作的编译器(根据定义)都不是有效的 Java 编译器。

How often does automatic promotion causing problem to you?

也许一年一次(我以编写 Java 代码为生)?

Is it possible to tweak the IDE so that it shows a warning to me when automatic promotion occurs? (I am using NetBeans IDE 7.3.1 at the moment.)

值得注意的是,这样的警告不会检测到需要显式提升的所有情况。例如,考虑:

boolean isNearOrigin(int x, int y, int r) {
return x * x + y + y < r * r;
}

即使没有自动提升,乘法也可能会溢出,这会使方法返回不正确的结果,应该这样写

    return (long) x * x + (long) y + y < (long) r * r;

相反。

同样值得注意的是,您建议的警告也会出现在正确的代码中。例如:

int x = ...;
foo(x);

如果使用参数类型 long 声明 foo,将警告自动升级,即使该升级不会产生任何不利影响。由于这种无辜的情况很常见,您的警告可能会很烦人,以至于每个人都会将其关闭。因此,如果发现任何 Java 编译器发出这样的警告,我会感到非常惊讶。

一般来说,编译器无法检测到操作会溢出,甚至找到可能溢出的候选对象也很复杂。鉴于溢出相关问题的罕见性,这种不完善的检测似乎是一个可疑的好处,这可能是 Java 编译器和 IDE 不实现它的原因。因此,程序员有责任为每个算术运算验证操作数类型提供的值集是否合适。这包括为用作操作数的任何数字文字指定合适的类型后缀。

PS:虽然我对你的纹波进位加法器工作印象深刻,但我认为你的 uAdd 方法可以更容易地实现如下:

long uAdd(long a, long b) {
long sum = a + b;
if (uLess(sum, a)) {
throw new ArithmeticException("Overflow");
} else {
return sum;
}
}

/** @return whether a < b, treating both a and b as unsigned longs */
boolean uLess(long a, long b) {
long signBit = 1L << -1;
return (signBit ^ a) < (signBit ^ b);
}

要了解为什么这是正确的,让 < 表示带符号解释的小于关系(相当于 Java 运算符),而 ≪ 表示无符号值的小于关系。令 a 和 b 为任意位模式,通过翻转符号位从中获得 a' 和 b'。根据有符号整数的定义,我们有:

  • 如果 sign(a) = sign(b),我们有 (a ≪ b) = (a' ≪ b') = (a' < b')
  • 如果 sign(a) ≠ sign(b),我们有 (a ≪ b) = (b' ≪ a') = (a' < b')

因此,(a ≪ b) = (a' < b')。

关于java - 如何禁用 Java 中的转化和促销?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25058224/

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