2

Here's the code and result:

python2.7 >>> 0xcafebabe
3405691582

scala2.10.4> 0xcafebabe
res0: Int = -889275714

Why is the hex number '0xcafebabe' a negative number in Scala?

P.S.: I find it related to the overflow of Int. But when I specify a variable as Long, why does it still not as expected?

scala> val aa = 0xcafebabeL
aa: Long = 3405691582

scala> val aa1:Long = 0xcafebabe
aa1: Long = -889275714

P.S. 2: When I try to evaluate a variable as Int with 3405691582, the Scala prompt complains error: integer number too large, whereas if 0xcafebabe is applied, no error is thrown. Why is that?

scala> val aa:Int = 3405691582
<console>:1: error: integer number too large
       val aa:Int = 3405691582
                    ^

scala> val aa:Int =  0xcafebabe
aa: Int = -889275714
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Judking
  • 6,111
  • 11
  • 55
  • 84
  • 2
    Because hex numbers are uint by default in python? (It has nothing to do with int overflow). – user3467349 Feb 14 '15 at 06:39
  • Try casting it as long? `val i : Long = 0xcafebabe` Seems like an integer overflow – Jesvin Jose Feb 14 '15 at 06:41
  • Yep, it is integer overflow, but a new problem occurred. Please check out my updated question. @aitchnyu – Judking Feb 14 '15 at 06:42
  • Once you enter `0xcafebabe` (without the L), you have created the number as a "normal" (not long) integer. Converting it to Long later doesn't change its value. – BrenBarn Feb 14 '15 at 06:43

3 Answers3

5

Python has arbitrary-precision integers, so the range of int is unlimited, akin to the BigInt of Scala, whereas in Scala, unqualified integer literals map to Java type int. Java int has 32-bits of precision with range -0x80000000 to 0x7FFFFFFF.

Since 0xcafebabe and 0xdeadbeef have the sign bit set, they are negative as ints in Java and other JVM languages; they are evaluated as the two's complement, as -0x21523502. This is not a question of overflow, but standard behaviour. In JVM there are no unsigned value types, and int is used for bitfields where all 32 bits can be set, tested and unset as needed; for such cases it is customary to use a positive hex constant to set all values from 0x00000000 for no bits set to 0xFFFFFFFF for all bits set.

In Scala, you can have positive 0xcafebabe if you make it a Long literal: try 0xcafebabeL. This will be understood as 3405691582L by Scala.

In JVM the overflow is well-defined for math operations; the calculations happen according to the two's complement math always; you could consider this as an example of integer overflow, but it is not, as the compiler just considers this 0xcafebabe to be exactly identical to the -889275714 literal.

Community
  • 1
  • 1
  • If it is overlow, why it doesn't throw an error as described in **P.S.2**? – Judking Feb 14 '15 at 06:48
  • 2
    Because 0xcafebabe is a negative 32bit number and 3405691582 is a positive 64 bit number, which I think follows from Antti's explanation. @Judking – user3467349 Feb 14 '15 at 06:50
1

In Python, integers are "bignums" that can represent numbers of any size. (Actually in Python 2 there are integers and long integers under the hood, but conversion between them is handled transparently, so they act as a single type.) The way Python defines integers does not tie them to a particular implementation at the bit level, and does not limit how large they may be. In Scala, integers are 32-bit and longs are 64-bit. The Scala language defines integers (and longs) as falling in a particular numerical range; numbers outside this range cannot be represented as integers in Scala.

As for your edit, once you enter 0xcafebabe without the L suffix, you are creating a plain int. Casting this to Long doesn't convert it to what it "would have been" if you had made it a long int initially, it just takes the value and makes it a long int. It doesn't know how you originally input the number, so for it knows you actually typed in -889275714. If you want to input a long integer literal you need to specify it as long when you input it.

This is also the reason you get an error for your second edit. Again, if you don't specify the literal as long, you are inputting a regular int; if your number cannot fit into a regular int, you get an error. (When you input the hex value, you are setting the individual bits of a 32-bit number, so you can create a negative number without using a negative sign, which is what you get when you enter a number that is "too big".)

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
0

In Python hex numbers are UInt types by default.

Which means:

>>> 0xff
255
>>> 0xcafebabe
3405691582

I don't use Scala, but I'm guessing the default type is a 32-bit int. I.e.:

>>> ctypes.c_int32(0xcafebabe)
c_int(-889275714)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user3467349
  • 3,043
  • 4
  • 34
  • 61
  • It is not really correct to say that Python ints (or hex literals) are uints. Python ints (regardless of what literal you use to input them) do not specify an implementation at that level; they are just integers, and can be either positive or negative. – BrenBarn Feb 14 '15 at 06:57
  • @BrenBarn Maybe that isn't perfectly worded, I meant to say that they don't use a sign bit (so in that sense a python hex number is equivalent to the corresponding c_uint). Of course it's possible to write `-0xff` – user3467349 Feb 14 '15 at 06:59