如何使用带有有符号字节的模数?

时间:2015-08-27 16:03:16

标签: java scala byte modulo signed

我想实现以下伪代码,其中/** * Get the format for database stored dates. * * @return string */ public function getDateFormat() { return 'Y-m-d H:i:s.u'; } /** * Convert a DateTime to a storable string. * SQL Server will not accept 6 digit second fragment (PHP default: see getDateFormat Y-m-d H:i:s.u) * trim three digits off the value returned from the parent. * * @param \DateTime|int $value * @return string */ public function fromDateTime($value) { return substr(parent::fromDateTime($value), 0, -3); } 是一个字节,a是一个字节。

b

我会在Scala中编写它,就像下面的代码片段一样,但我不认为Java会有很大的不同。

因此,如果字节值的范围从0到255(含),我可以写:

(a + b) mod 256

但Java / Scala类型(a + b) % 256 已签名,范围从-128到127(含)。我可以写:

Byte

这对我来说似乎不必要地复杂,但我不知道def f1(a: Byte, b: Byte): Byte = (((a + 128 + b + 128) % 256) - 128).toByte 对负值的行为如何。此外,我不知道是否可以使用xor或类似的东西简化此功能。

如何根据%类型实现和简化功能?

或更一般:

如何使用带有符号字节的模数?

修改

上面的函数f1不正确。应该是:

Byte

因为我的,与简化版本的比较是错误的。所以这种简化的方法应该有效:

def f1(a: Byte, b: Byte): Byte = ((a + b + 128) % 256 - 128).toByte

这两个值隐式转换为def f2(a: Byte, b: Byte): Byte = (a + b).toByte 值并一起添加。将其转换回Int时,结果Byte的前4个字节中的前3个将被删除,等于模运算。函数Intf1现在返回相同的结果。测试了所有256 * 256种可能的输入变化。

2 个答案:

答案 0 :(得分:0)

这是一个简化版本:

def f2(a: Byte, b: Byte): Byte = (a + b).toByte

我编辑了这个问题并在那里解释了答案,因为我犯了一个错误,包含在问题中。

答案 1 :(得分:0)

在Java中,模数运算符%可以产生0或与被除数相同的符号:

-1 % 256 = -1.

此外,即使使用Java的签名byte类型,也可以将位模式解释为无符号值。

100000000 = -128 (signed) = 128 (signed)

此外,执行byte算术mod 256是多余的,因为回退到byte会隐式执行此操作。

现在让我们看看在每个溢出(有符号和无符号)的情况下会发生什么:

public static void addMod256(byte a, byte b)
{
    byte c = (byte) (a + b);
    System.out.println("(" + a + " + " +  b + ") % 256 = " + c +
        ".  Unsigned: (" +
        (a & 0xFF) + " + " + (b & 0xFF) + ") % 256 = " + (c & 0xFF) + ".");
}

addMod256((byte) 6, (byte) 70);     // No overflow in signed or unsigned bytes
addMod256((byte) 70, (byte) 70);    // Overflow only in signed bytes
addMod256((byte) -6, (byte) -70);   // Overflow only in unsigned bytes
addMod256((byte) -120, (byte) -120);// Overflow in both signed and unsigned bytes

输出:

(6 + 70) % 256 = 76.  Unsigned: (6 + 70) % 256 = 76.
(70 + 70) % 256 = -116.  Unsigned: (70 + 70) % 256 = 140.
(-6 + -70) % 256 = -76.  Unsigned: (250 + 186) % 256 = 180.
(-120 + -120) % 256 = 16.  Unsigned: (136 + 136) % 256 = 16.

无论出现什么溢出情况,结果都是正确的。因此,在Java中,您只需添加它们并将结果转换回byte

public static byte f1(byte a, byte b)
{
    return (byte) (a + b);
}

在Scala中,等价物就像你已经指出的那样:

def f2(a: Byte, b: Byte): Byte = (a + b).toByte