Java Scala 中的无符号变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21212993/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 07:22:00  来源:igfitidea点击:

Unsigned variables in Scala

javascala

提问by

I am converting some C code to Scala as we are moving (allegedly) into the Modern world here in Corporate towers, or so I have been told anyways.

我正在将一些 C 代码转换为 Scala,因为我们正在(据称)进入现代世界的公司塔楼,或者我被告知无论如何。

Some of the C code uses unsigned variables that have a significant number of bit level (shift) operations performed upon them.

一些 C 代码使用无符号变量,这些变量对它们执行了大量的位级(移位)操作。

I am at a complete standstill on how to convert these to Scala, given that I believe both Scala (and Java) and indeed the JVM find unsigned types alien.

鉴于我相信 Scala(和 Java)和实际上 JVM 都发现了无符号类型,我完全停止了如何将它们转换为 Scala。

Any advice appreciated.

任何建议表示赞赏。

采纳答案by DaoWen

The only difference between signed an unsigned math in C and on the JVM comes up with the right-shift operator. For unsigned math, you use logical shift(since you don't want sign extension), whereas for signed math you do an arithmetic shift(which preserves the sign). This is one of the beauties of Two's complement arithmetic.

在 C 和 JVM 上有符号的无符号数学之间的唯一区别在于右移运算符。对于无符号数学,您使用逻辑移位(因为您不需要符号扩展),而对于有符号数学,您使用算术移位(保留符号)。这是二进制补码算法的优点之一。

Based on that, all you have to do is change the Java/Scala >>operator for the >>>operator, and you'll get the same answer, bit-by-bit. However, depending on what you're doing it might still be problematic when you try to do something with the result, e.g. if you want to print it as an unsigned integer.

基于此,您所要做的就是更改>>运算符的 Java/Scala运算>>>符,并且您将一点一点地得到相同的答案。但是,根据您在做什么,当您尝试对结果执行某些操作时,它可能仍然存在问题,例如,如果您想将其打印为无符号整数。

Let's say you want to do some math with "unsigned" longs in Scala and print the result at the end. Just use a normal long, use the >>>(logical shift) operator in place of >>, and then convert it to something else at the end that can represent the unsigned value. You could use a library like suggested in @rightfold's answer, or you can just do something simple like this:

假设您想在 Scala 中用“无符号”长整型做一些数学运算,并在最后打印结果。只需使用普通的 long,使用>>>逻辑移位)运算符代替>>,然后在最后将其转换为可以表示无符号值的其他内容。您可以使用@rightfold 的答案中建议的库,或者您可以执行以下简单的操作:

val x = Long.MaxValue // declare my "unsigned" long
// do some math with it ...
val y = x + 10

// Convert it to the equivalent Scala BigInt
def asUnsigned(unsignedLong: Long) =
  (BigInt(unsignedLong >>> 1) << 1) + (unsignedLong & 1)

x
// Long = 9223372036854775807
asUnsigned(y)
// res1: scala.math.BigInt = 9223372036854775817

If you're just using Ints, then you don't even have to convert to BigIntat the end since a Longcan hold the answer. Just use the method that @BrianRoach suggests in his comment above to convert an Int's "unsigned" value to the equivalent Longby masking-off the higher-order bytes. However, again, you shouldn't do the conversion until you absolutely have to. Even when using a 64-bit JVM on a 64-bit processor, the integer multiply and divide operations will be slower for a Long(64-bit) than for an Int(32-bit). (See this question for more details: Are 64 bit integers less efficient than 32 bit integers in the JVM?).

如果您只是使用Ints,那么您甚至不必BigInt在最后转换为,因为 aLong可以保存答案。只需使用@BrianRoach 在上面的评论中建议的方法,通过屏蔽高阶字节将Int的“无符号”值转换为等效值Long。但是,在绝对必要之前,您不应该进行转换。即使在 64 位处理器上使用 64 位 JVM,整数乘法和除法运算对于Long(64 位)也比Int(32 位)慢。(有关更多详细信息,请参阅此问题:在 JVM 中 64 位整数是否比 32 位整数效率低?)。

回答by rightfold

The JVM unfortunately does not support unsigned data types (besides char, thanks Erwin), but there is hope! Scala has a sufficiently advanced type system that allows you to create your own types that act like unsigned types!

不幸的是,JVM 不支持无符号数据类型(此外char,感谢 Erwin),但还是有希望的!Scala 有一个足够先进的类型系统,允许您创建自己的类型,其行为类似于无符号类型!

There is even a librarythat already does it! The library overloads the operators and provides conversions.

甚至有一个图书馆已经这样做了!该库重载运算符并提供转换。