working with bytes (aka UInt8 aka Data)

Hello,


It may sound like a very trivial question (well I'm a noob after all) but I've been searching everywhere all evening and my head hurts : How do you add bytes ? I want to calculate the sum of 8 bytes:


I tried:


Let data : [UInt8] = [0xFF,0xF0,0x0F,0x11,0xFF,0xFF,0xF0,0x0F]


let total = data.reduce(0, +)
let numberSum = data.reduce(0, { x, y in x + y})


var sum : UInt8 = 0
for i in 0...data.count-1 {
  sum += data[i]
}


reduce() does not seem to work with an array of UInt8 but it works with arrays of Int

The loop does not work either, I cannot find the right format for sum and I cannot manage the overflow when I +=


The final goal of all this is to calculate a simple checksum. I came across some very complex methods and I am sure there is a simplier way. The code below shows how I did it in C++ (Arduino):


byte data[]={0xFF,0xF0,0x0F,0x11,0xFF,0xFF,0xF0,0x0F}; 

byte sum = 0;
  for ( int i=0; i<sizeof(data); i++) {
    sum += data[i];
  }
byte checksum = lowByte(sum);

// sum = 1292 (0x50C) checksum = C


Any idea ?


Thanks

Accepted Answer

You can't add those things up as UInt8 values, because they overflow — immediately after the first one, which is 256. Instead, you need to do a calculation where you convert each byte to a larger type (Int or UInt or something like that).


It works in C++ (or C) because integers smaller than "int" are automatically promoted to "int" for such calculations. There is no such automatic promotion in Swift.

Thanks QuinceyMorris,


I've already tried that (didn't post all things I tried...) :


var sum : Int = 0
for i in 0...data.count-1 {
  sum += Int(data[i])
}

print(sum)
let hexsum = String(sum, radix: 16)
print(hexsum)


the "sum" is ok but then I don't know how to get the last 8 bits (i.e. lowByte() ). My "hesum" looks ok but is in reality just a useless string...

That was another dead end for me, that's why I didn't post it...




Just now I tried :

let chkSum1 = UInt8(truncatingIfNeeded: sum)
let chkSum2 = sum & 255


and it works !!!


Thanks QM


PS: which of the two methods would be preffered : truncatingIfNeeded or &255 ?

which of the two methods would be preffered : truncatingIfNeeded or &255 ?

Neither. If you’re doing a checksum calculation then you want to work in the sum space (

UInt8
in this case) and use wrapping addition, which Swift supports via the
&+
operator. For example:
let data: [UInt8] = [0xFF,0xF0,0x0F,0x11,0xFF,0xFF,0xF0,0x0F]
let sum = data.reduce(0) { (soFar, byte) in
    soFar &+ byte
}

Or if you’re suspicious of all this new-fangled functional programming stuff (-: and just want to use a loop:

let data: [UInt8] = [0xFF,0xF0,0x0F,0x11,0xFF,0xFF,0xF0,0x0F]
var sum = 0 as UInt8
for byte in data {
    sum &+= byte
}

Note that I’m using

&+=
here, which is the wrapping form of
+=
.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
working with bytes (aka UInt8 aka Data)
 
 
Q