Scala中的无符号变量 [英] Unsigned variables in Scala

查看:954
本文介绍了Scala中的无符号变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将一些C代码转换为Scala,因为我们正在公司大楼中移动(据称)进入现代世界,或者因此我被告知。

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代码使用无符号变量,这些变量对它们执行了大量的位级(移位)操作。

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

我完全停止了如何转换它们Scala,因为我相信Scala(和Java)以及JVM确实找到了unsigned类型的外星人。

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.

任何建议都值得赞赏。

推荐答案

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

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.

基于此,您所要做的就是更改>的Java / Scala >> 运算符;>> 运算符,你会得到相同的答案,一点一滴。但是,根据您正在进行的操作,当您尝试对结果执行某些操作时,可能仍会出现问题,例如:如果你想把它打印成无符号整数。

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.

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

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:

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

如果您只是使用 Int s,那么您甚至不必转换为 BigInt 结尾,因为 Long 可以得到答案。只需使用@BrianRoach在上面评论中建议的方法将 Int 的unsigned值转换为等效的 Long 通过屏蔽高阶字节。但是,再次,您绝不应该进行转换。即使在64位处理器上使用64位JVM,对于 Long (64位),整数乘法和除法运算也会比<$ $慢。 c $ c> Int (32位)。 (有关更多详细信息,请参阅此问题: 64位整数的效率低于JVM中的32位整数吗?)。

If you're just using Ints, then you don't even have to convert to BigInt at the end since a Long can hold the answer. Just use the method that @BrianRoach suggests in his comment above to convert an Int's "unsigned" value to the equivalent Long by 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?).

这篇关于Scala中的无符号变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆