Cosmo/BinaryKit

I'm sure I'm doing something wrong

RolandasRazma opened this issue · 7 comments

I'm sure I'm doing something wrong, could you point me right direction please? Im trying to read signed value but not sure how to correctly read negative one.

I added category to accomplish this

extension Binary {
    
    mutating func readSignedBits(quantitiy: Int) throws -> Int {
        
        if try readBit() == 1 {
            let bit = try readBits(quantitiy: quantitiy - 1)

            let bitsReversed = String(String(bit, radix: 2).map({ $0 == "1" ? "0" : "1" }))
            return -Int(bitsReversed, radix: 2)! - 1
        } else {
            return try readBits(quantitiy: quantitiy - 1)
        }
        
    }
    
}

but it doesn't "feel" right

Cosmo commented

Hi @RolandasRazma,
big sorry — for some reason I didn't notice your issue!

I think, this should do the trick:

extension Binary {
    mutating func readSignedBits(_ quantitiy: UInt8) throws -> Int {
        let multiplicationFactor = (try readBit() == 1) ? -1 : 1
        let value = try readBits(quantitiy - 1)
        return value * multiplicationFactor
    }
}

It's similar of what you do. First, I tell how many bits I actually want to read.
Then I read the first bit to determine if the value is positive (0) or negative (1).
Then I read the remaining bits and multiply the integer value of those bits by 1 (positive) or by -1 (negative).

hi, no worries, thanks for reply, will try it out

hm, this gives different result from what I get

Cosmo commented

Weird, can you give me an example?

 var binary = Binary(bytes: [252, 100, 99, 4, 254, 129, 98, 19, 254, 3, 200, 192])
 _ = try! binary.readBits(quantitiy: 32)
        
XCTAssertEqual(try binary.readSignedBits(quantitiy: 10), -6) // My implementation returns -6, yours -250
XCTAssertEqual(try binary.readSignedBits(quantitiy: 10), 22)
XCTAssertEqual(try binary.readSignedBits(quantitiy: 10), 132)

P.S. tested on 3.0.1

Cosmo commented

Hmm weird — on my machine
try binary.readSignedBits(10)
returns -506.

This is what I did for debugging:

  1. I took var binary = Binary(bytes: [252, 100, 99, 4, 254, 129, 98, 19, 254, 3, 200, 192]) from your example
  2. Next is _ = try! binary.readBits(quantity: 32). Which basically means: "skip the first 4 bytes" (side note: i realized that i have a typo in the word "quantity" throughout my repo. whoops!)
  3. Skipping the first 4 bytes leaves the array with [254, 129, 98, 19, 254, 3, 200, 192] (removing the first 4 elements)
  4. [254, 129, 98, 19, 254, 3, 200, 192] in hex is [0xFE, 0x81, 0x62, 0x13, 0xFE, 0x03, 0xC8, 0xC0] and conveniently are 8 bytes which fit in the calculator app.
  5. In the calculator app, it looks like this (see screenshot) and shows me a binary representation.

image

  1. Take the first 10 bits (11 1111 1010) as in your first XCTAssertEqual.
  2. The first bit determines if the following 9 bits are positive or negative. In this case, the first bit is 1 which means the integer will be on the negative side.
  3. The remaining bits 1 1111 1010 are 506 in decimal.
  4. Together with the sign, its -506

Did I miss anything?