First some expected behaviour in finding the integer ranges:
print("Int8 range: \(Int8.min) ... \(Int8.max)")
print("UInt8 range: \(UInt8.min) ... \(UInt8.max)")
print("Int16 range: \(Int16.min) ... \(Int16.max)")
print("UInt16 range: \(UInt16.min) ... \(UInt16.max)")
print("Int32 range: \(Int32.min) ... \(Int32.max)")
print("UInt32 range: \(UInt32.min) ... \(UInt32.max)")
print("Int64 range: \(Int64.min) ... \(Int64.max)")
print("UInt64 range: \(UInt64.min) ... \(UInt64.max)")
This prints:
Int8 range: -128 ... 127
UInt8 range: 0 ... 255
Int16 range: -32768 ... 32767
UInt16 range: 0 ... 65535
Int32 range: -2147483648 ... 2147483647
UInt32 range: 0 ... 4294967295
Int64 range: -9223372036854775808 ... 9223372036854775807
UInt64 range: 0 ... 18446744073709551615
As I said, that was to be expected. But pay attention to the Int64 and UInt64
Now some expected behaviour for NSNumber:
var n = NSNumber(value: 0x1020304050607080)
print("Int8: \(n.int8Value)")
print("UInt8: \(n.uint8Value)")
print("Int16: \(n.int16Value)")
print("UInt16: \(n.uint16Value)")
print("Int32: \(n.int32Value)")
print("UInt32: \(n.uint32Value)")
print("Int64: \(n.int64Value)")
print("UInt64: \(n.uint64Value)")
Prints:
Int8: -128
UInt8: 128
Int16: 28800
UInt16: 28800
Int32: 1348497536
UInt32: 1348497536
Int64: 1161981756646125696
UInt64: 1161981756646125696
Interesting, here we see that the integers don't clip (or clamp) to max, but are in effect simple bit mapped conversions. For example the -128 for the Int8 is clearly caused by the ....80 at the end of the literal.
We can make this even clearer by:
var n = NSNumber(value: 0x1020304080608080)
...
Output:
Int8: -128
UInt8: 128
Int16: -32640
UInt16: 32896
Int32: -2141159296
UInt32: 2153808000
Int64: 1161981757451436160
UInt64: 1161981757451436160
So far so good.
So what would we expect if the we change 0x1020.. to 0x8020..
I don't know about you, but I would expect the Int64 to go negative and the UInt64 to remain positive.
However:
var n = NSNumber(value: 0x8020304080608080)
Generates the error:
Playground execution failed: error: MyPlayground8.playground:8:25: error: integer literal '9232432289699364992' overflows when stored into 'Int'
So let's fix that by:
var n = NSNumber(value: UInt64(0x8020304080608080))
No such luck, the same error occurs.
Next step:
var k: UInt64 = 0x8020304080608080
var n = NSNumber(value: k)
...
Int8: -128
UInt8: 128
Int16: -32640
UInt16: 32896
Int32: -2141159296
UInt32: 2153808000
Int64: -9214311784010186624
UInt64: 9232432289699364992
Now, what would happen when NSNumber is initialized from a float or double?
Try that:
var n = NSNumber(value: 10.0)
...
Int8: 10
UInt8: 10
Int16: 10
UInt16: 10
Int32: 10
UInt32: 10
Int64: 10
UInt64: 10
var n = NSNumber(value: -10.0)
...
Int8: -10
UInt8: 246
Int16: -10
UInt16: 65526
Int32: -10
UInt32: 4294967286
Int64: -10
UInt64: 18446744073709551606
How about rounding?
var n = NSNumber(value: 10.8)
...
Int8: 10
UInt8: 10
Int16: 10
UInt16: 10
Int32: 10
UInt32: 10
Int64: 10
UInt64: 10
Nope, no rounding here (expected behaviour)
var n = NSNumber(value: -10.8)
...
Int8: -10
UInt8: 246
Int16: -10
UInt16: 65526
Int32: -10
UInt32: 4294967286
Int64: -10
UInt64: 18446744073709551605
This may seem strange, but I am content to call that expected behaviour. As long as we keep in mind that rounding down is always in the direction of 0. Even for negative numbers.
Now, lets get wild:
var n = NSNumber(value: 1e10)
...
Int8: 0
UInt8: 0
Int16: -7168
UInt16: 58368
Int32: 1410065408
UInt32: 1410065408
Int64: 10000000000
UInt64: 10000000000
Ok, not all that wild, still as expected. Lets get wilder still. But keep in mind that 100.000.000 is a special number, it translates to 0x5F5E100, which is to say that all multiples of that number will also result in 0xXXXXXX00. Thus simply multiplying 100.000.000 by *10 and again, and again will eventually create 0 values for all Int's.
Weird things start to happen at 1e19:
var n = NSNumber(value: 1e19)
...
Int8: 0
UInt8: 0
Int16: 0
UInt16: 0
Int32: 0
UInt32: 0
Int64: -9223372036854775808
UInt64: 10000000000000000000
And this behaviour continues as we use ever greater numbers. And with much bigger numbers the clipping behaviour also occurs in the UInt64 (at 1e39):
var n = NSNumber(value: 1e39)
...
Int8: 0
UInt8: 0
Int16: 0
UInt16: 0
Int32: 0
UInt32: 0
Int64: -9223372036854775808
UInt64: 18446744073709551615
Well, now you know...
Happy coding...
Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH
We don't get the world we wish for... we get the world we pay for.