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.

## No comments:

## Post a Comment