Question

I apologize if this question has been answered already but I have not been able to find what I am looking for.

I am working in c++ with an SPI device. The SPI device outputs data in 16 bit words in 2's complement form. I am trying to convert this data into decimal for use with a filter.

I've attached some sample code that asks the user to input a number in twos complement and then outputs the signed decimal version.

#include <iostream>     
#include <stdlib.h>
#include <cstdint>
#include <cmath>
#include <bitset>
using std::cout;
using std::endl;
using std::cin;
using std::hex;
using std::dec;
using std::bitset;
int main () {
    uint16_t x2=0;
    cout<<"Please enter the number you would like to convert from 2's complement.  "<<endl;
    cin>>x2;
    int diff=0x0000-x2;
    cout<<"The number you have entered is: "<<dec<<diff<<endl;
return 0;
}

When I run this program and input something like 0x3B4A it always outputs 0. I'm not entirely sure what is going on and I'm very new to c++ so please excuse me if this is a stupid question. Also, please ignore anything extra in the header. This is partof a large project and I couldn't remember what parts of the header go with this specific section of code.

Thanks!

Edit: This is mostly for Ben. After reading your most recent comment I made the following changes but am still simply getting the decimal equivalent of the hexadecimal number I entered

#include <iostream>     
#include <stdlib.h>
#include <cstdint>
#include <cmath>
#include <bitset>
using std::cout;
using std::endl;
using std::cin;
using std::hex;
using std::dec;
using std::bitset;
int main () {
    int16_t x2=0;
    cout<<"Please enter the number you would like to convert from 2's complement.  "<<endl;
    cin>>hex>>x2;
    int flags= (x2>>14) & 3;
    int16_t value=(x2 << 2) >> 2;
    cout<<"The number you have entered is: "<<dec<<value<<endl;
return 0;
}
Was it helpful?

Solution 3

The standard library function strtol converts string input to a number, and supports the 0x prefix as long as you pass 0 as the radix argument.

Since int16_t is almost certainly 16-bit two's complement signed, you can just use that.

OTHER TIPS

I'm not sure it is necessary for the OP's question, but for anybody who is just looking for the formula for converting a 16bit 2's complement unsigned integer to a signed integer, I think a variant of it looks like this (for input val):

(0x8000&val ? (int)(0x7FFF&val)-0x8000 : val)

This amounts to:

  • if first bit is 1, it is a negative number with all other bits in 2's complement
  • extract negative part by subtracting off the 0x8000
  • otherwise the lower bits are just the positive integer value

Probably a good idea to wrap this in a function and do some basic error checking (can also enforce that the input is actually an unsigned 16 bit integer).

You asked cin to read as decimal (by making no format changes) so as soon as it reads the x, which is not a 0-9 digit, it stops, leaving you with zero.

Just add hex to your cin line: cin >> hex >> x2;

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top