3

my simple encryption algorithim i am doing as an exercise is giving me a possible lossy conversion from int to byte? but i dont know why it is giving me this error any ideas?

public class Rot13Crypt extends CryptStream
{
    public Rot13Crypt(StreamPair theStreams)
    {
        super(theStreams);
    }
    protected byte [] cryptData(byte [] data, int len)
    {
        byte [] cryptedByte = new byte[len];
        for(int i = 0; i < len; i++)
        {
            cryptedByte[i] = (data[i] + 13) % 256;
        }
        return cryptedByte;
    }
    protected byte [] decryptData(byte [] data, int len)
    {
        byte [] decryptedByte = new byte[len];
        for(int i = 0; i < len; i++)
        {
            decryptedByte[i] = (data[i] * 256) - 13;
        }
        return decryptedByte;
    }
}
Hotfin
  • 97
  • 2
  • 2
  • 5

7 Answers7

5

It is giving that error message because you are attempting to assign the value of an int-valued expression to a byte. That is a potentially lossy operation: intuitively, you cannot put all possible int values into a byte.

The Java language requires you to use a (byte) cast when you assign an int-valued expression to a byte.

There are two places where you are doing this:

   cryptedByte[i] = (data[i] + 13) % 256;

   decryptedByte[i] = (data[i] * 256) - 13;

In the first one, the value of the expression is in the range 0 to 255 ... but Java byte values are in the range -128 to +127.

In the second one, the expression values potentially have values in the range (-128 * 256) - 13 to `(+127 * 256) - 13. That clearly won't fit.

But that is actually moot. The Java does not allow variants of the above code even if you (a smart human being) can prove that the range of the expression would "fit" into a byte. The JLS forbids this. (A Java compiler not required to be a general theorem prover!!)

The only situation where an int-valued expression can be assigned to a byte without a type-cast is when the expression is a compile-time constant expression AND the actual value of the expression is in the range of byte.

If you are interested, this is specified in JLS 15.2 Assignment Contexts which states:

In addition, if the expression is a constant expression (§15.28) of type byte, short, char, or int:

  • A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.

(You need to chase down what the spec means by "constant expression" and "narrowing primitive conversion". I'll leave that for interested people to do for themselves.)


so would i add a (byte) cast in front of the 13 and 256?

Nope. You need to cast the entire expression; e.g.

   cryptedByte[i] = (byte) ((data[i] + 13) % 256);
Community
  • 1
  • 1
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
3

In Java, the int type is coded using 32 bits and the byte type using 8 bits. If you convert an int to a byte, you may lose information if your original value is greater than 127 or less than -128.

An integer literal is by default an int and operations on int return int. So the result of data[i] + 13 is an int; the same for (data[i] + 13) % 256. When you try to store that result into a byte (here cryptedByte[i]), Java warns you about the "possible lossy conversion".

osechet
  • 426
  • 3
  • 11
1

A byte has 2^8 = 256 unique states and so the largest range it can represent is -128 to 127.

so assuming that in

 decryptedByte[i] = (data[i] * 256) - 13;

the data[i] value is greater than 1 will cause the value to overflow the max value of a byte

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
Scary Wombat
  • 44,617
  • 6
  • 35
  • 64
0

You have problems here

cryptedByte[i] = (data[i] + 13) % 256;

and here

decryptedByte[i] = (data[i] * 256) - 13;

256 and 13 are literals of type int. When you perform operations with them and with a type that occupies less memory (in this example, byte), type promotion occurs: data[i] is implicitly converted (promoted) to type int. Thus, both these expressions evaluate to int. And you know what happens when you convert an int to a byte, right? You can lose data. That is because a byte is limited to less memory than int.

0

You just need to do a cast when assigning each byte when it's inside a variable, so java can assure all are between -127 and 127 which is the ascii range. The folowing should work:

public class Rot13Crypt extends CryptStream
{
    public Rot13Crypt(StreamPair theStreams)
    {
        super(theStreams);
    }
    protected byte [] cryptData(byte [] data, int len)
    {
        byte [] cryptedByte = new byte[len];
        for(int i = 0; i < len; i++)
        {
            cryptedByte[i] = (byte) (data[i] + 13) % 256;
        }
        return cryptedByte;
    }
    protected byte [] decryptData(byte [] data, int len)
    {
        byte [] decryptedByte = new byte[len];
        for(int i = 0; i < len; i++)
        {
            decryptedByte[i] = (byte) (data[i] * 256) - 13;
        }
        return decryptedByte;
    }

}

Maf
  • 696
  • 1
  • 8
  • 23
-1

Bytes have a size of 8 bits and ints a size of 32 bits. So some information may be lost by doing this conversion!

Juce
  • 341
  • 1
  • 8
-1

byte data type is an 8-bit signed two's complement integer. int data type is a 32-bit signed two's complement integer.

Can't fit an integer into a byte. Hence, the loss in precision. I hope it's clear.

A sample reference is here

Gyan
  • 1,176
  • 1
  • 12
  • 26