Converting sensor data (two's complement) to signed integer - c++

I've seen a couple old posts that had a similar context but the answers were code snippets, not explanatory. And I can't even get the code offered in those answers to compile.
I apologize in advance if this is poorly formatted or explained, I am new to C++ and I avoid asking questions on forums at all costs but this has become a real thorn in my side.
I am using C++ to access the memory register of an accelerometer.
This register contains 8 bits of data in the form of twos complement.
The accelerometer is set to have a range of +/- 2 g's, meaning (see section 1.5 of reference manual on page 10)
My goal is to take this twos complement data and save it to a text file as signed base-10 data.
Relevant code below:
while(1)
{
int d = 0;
d= wiringPiI2CReadReg8(fd, DATA_X_H);
d = (int8_t)d;
d = d * EIGHTBITCONV;
std::cout << d << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
I've tested the program by hard coding "d" as 01111111 (127) and the program returns "73". But hard coding "d" as 10000001 (-127) and the program returns the correct "-127".
So the program only functions properly when dealing with negative numbers.
Is this happening because when casting the float "d" to an 8bit integer it truncates the leading zero for positive numbers? How would I fix this?
Link to datasheet: https://www.mouser.com/datasheet/2/348/KX132-1211-Technical-Reference-Manual-Rev-1.0-1652679.pdf

You do not need to convert from 2's complement to "signed integer", because 2's complement is signed integer.
You are only reading 8 bits, but int (the return type of wiringPiI2CReadReg8) has more. So you need a sign-extend conversion. Something like:
int result = (int)(signed char)wiringPiI2CReadReg8(fd, DATA_X_H);
The (int) conversion is implicit and can be omitted. And in your case you are converting to a float (The conversion is again implicit). So:
d = (signed char)wiringPiI2CReadReg8(fd, DATA_X_H);
Actually your solution (negating twice) would work as well. More explicitly it could be written like this (since 1 is int):
d = -((int)(~(int8_t)d) + 1);
But this is just unnecessary work. It could be simplified to be:
d = -(-(int8_t)d);
and now it is obviously simplifies into:
d = (int8_t)d;
same as what I wrote before.

Ok so I think a lot of my confusion came from the fact that I was trying hard code values into my program without proper knowledge of how to do so.
If I were to do hard coding as a method to test the logic, I should have specified that the values of "d" were binary.
So it looks like my original code, while extremely sloppy, was functioning properly.

Related

Hexadecimal vs Decimal in C++

So the following code
#include <stdio.h>
int main() {
int myInt;
myInt = 0xFFFFFFE2;
printf("%d\n",myInt);
return 0;
}
yields -30.
I get the idea of two's complement but when I directly type -30 I get the same number too. So my question is why would I write my number in hexadecimal form ? And if I use hexadecimal form how does the compiler distinguish between whether I mean 0xFFFFFFE2 is two's complement for -30 or the value 4294967266?
Edit: This has nothing to do with two's complement as I later on find out. Two's complement is just a design way for cpu's to operate on integers in a more efficient way. [For more information Wiki]. See #Lightness Races in Orbit 's answer for explanation of the above code.
There are some misconceptions here, all of which can be fixed by revisiting first principles:
A number is a number.
When you write the decimal literal 42, that is the number 42.
When you write the hexadecimal literal 0x2A, that is still the number 42.
When you assign either of these expressions to an int, the int contains the number 42.
A number is a number.
Which base you used does not matter. It changes nothing. Writing a literal in hex then assigning it to an int does not change what happens. It does not magically make the number be interpreted or handled or represented any differently.
A number is a number.
What you've done here is assign 0xFFFFFFE2, which is the number 4294967266, to myInt. That number is larger than the maximum value of a [signed] int on your platform, so it overflows. The results are undefined, but you happen to be seeing a "wrap around" to -30, probably due to how two's complement representation works and is implemented in your computer's chips and memory.
That's it.
It's got nothing to do with hexadecimal, so there's no "choice" to be made between hex and decimal literals. The same thing would happen if you used a decimal literal:
myInt = 4294967266;
Furthermore, if you were looking for a way to "trigger" this wrap-around behaviour, don't, because the overflow has undefined behaviour.
If you want to manipulate the raw bits and bytes that make up myInt, you can alias it via a char*, unsigned char* or std::byte*, and play around that way.
Hexidecimal vs decimal has nothing at all to do with why it is displaying -30 or not.
For a 32 bit word that is being treated as signed (since you are using %d), any unsigned number that is greater than 2147483648 will be treated as a negative (2s complement number)
so, myInt could be -30, 0xFFFFFFE2, 4294967266 or -0x1E, and treating it as a signed 32 bit integer will display as -30.

Need help formatting numbers C++ [duplicate]

This question already has answers here:
Extract fractional part of double *efficiently* in C
(7 answers)
Closed 6 years ago.
Can someone help a rookie? If i have a number 4.561 that is derived from an equation, how can i ONLY display the .561 and ignore the 4?
Thanks in advance. I am new to programming and this is part of an assignment. Any help would be greatly appreciated. I'm coding in c++.
Not sure if this is what you need but do check this out.
float f = 4.561;
f = f-(long)f;
cout << "Value of f is : " << f << endl;
I would feel much better with using floor from math.h:
f = 4.561
if (f>=0) f=f-floor(f);
else f=f-ceil(f);
// here f = 0.561
for these reasons:
As you do not have control over casting to integral type (f-long(f)) at least I do not know if it is clearly defined as a standard it is using integer part or rounding. Not to mention custom types implementation.
what if your floating value holds bigger number then your integral type can hold? I know there are not that many mantissa bits for fractional part for bigger numbers but you did not specify which floating data-type you are using if 32/64/80/128/256 bits or more so hard to say and if the integer part is bigger then your integral data-type used to cut off the non fractional part then you would be in trouble with f-long(f).
PS.
The if statement could be avoided with masking in and out the sign bit before and after the operation. For example on standard 32bit float it looks like this:
float f=4.561; // input value
DWORD *dw=(DWORD*)(&f); // pointer to f as integer type to access bits
DWORD m; // sign storage
m=(*dw)&0x80000000; // store sign bit to m
(*dw)&= 0x7FFFFFFF; // f=fabs(f)
f-=floor(f);
(*dw)|=m; // restore original sign from m
// here f = 0.561
If you do not have DWORD use any unsigned 32 bit integer instead

Converting double to array of bits for genetic algorithm in C(++) [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Floating Point to Binary Value(C++)
Currently I'm working on a genetic algorithm for my thesis and I'm trying to optimize a problem which takes three doubles to be the genome for a particular solution. For the breeding of these doubles I would like to use a binary representation of these doubles and for this I'll have to convert the doubles to their binary representation. I've searched for this, but can't find a clear solution, unfortunately.
How to do this? Is there a library function to do this, as there is in Java? Any help is greatly appreciated.
What about:
double d = 1234;
unsigned char *b = (unsigned char *)&d;
Assuming a double consists of 8 bytes you could use b[0] ... b[7].
Another possibility is:
long long x = *(long long *)&d;
Since you tag the question C++ I would use a reinterpret_cast
For the genetic algorithm what you probably really want is treating the mantissa, exponent and sign of your doubles independently. See "how can I extract the mantissa of a double"
Why do you want to use a binary representation? Just because something is more popular, does not mean that it is the solution to your specific problem.
There is a known genome representation called real that you can use to solve your problem without being submitted to several issues of the binary representation, such as hamming cliffs and different mutation values.
Please notice that I am not talking about cutting-edge, experimental stuff. This 1991 paper already describes the issue I am talking about. If you are spanish or portuguese speaking, I could point you to my personal book on GA, but there are beutiful references in English, such as Melanie Mitchell's or Eiben's books that could describe this issue more deeply.
The important thing to have in mind is that you need to tailor the genetic algorithm to your problem, not modify your needs in order to be able to use a specific type of GA.
I wouldn't convert it into an array. I guess if you do genetic stuff it should be performant. If I were you I would use an integer type (like suggested from irrelephant) and then do the mutation and crossover stuff with int operations.
If you don't do that you're always converting it back and forth. And for crossover you have to iterate through the 64 elements.
Here an example for crossover:
__int64 crossover(__int64 a, __int64 b, int x) {
__int64 mask1 = ...; // left most x bits
__int64 mask2 = ...; // right most 64-x bits
return (a & mask1) + (b & mask2);
}
And for selection, you can just cast it back to a double.
You could do it like this:
// Assuming a DOUBLE is 64bits
double d = 42.0; // just a random double
char* bits = (char*)&d; // access my double byte-by-byte
int array[64]; // result
for (int i = 0, k = 63; i < 8; ++i) // for each byte of my double
for (char j = 0; j < 8; ++j, --k) // for each bit of each byte of my double
array[k] = (bits[i] >> j) & 1; // is the Jth bit of the current byte 1?
Good luck
Either start with a binary representation of the genome and then use one-point or two-point crossover operators, or, if you want to use a real encoding for your GA then please use the simulated binary crossover(SBX) operator for crossover. Most modern GA implementation use real coded representation and a corresponding crossover and mutation operator.
You could use an int (or variant thereof).
The trick is to encode a float of 12.34 as an int of 1234.
Therefore you just need to cast to a float & divide by 100 during the fitness function, and do all your mutation & crossover on an integer.
Gotchas:
Beware the loss of precision if you actually need the nth bit.
Beware the sign bit.
Beware the difference in range between floats & ints.

Differences in assignment of integer variable

I just asked this question and it got me thinking if there is any reason
1)why you would assign a int variable using hexidecimal or octal instead of decimal and
2)what are the difference between the different way of assignment
int a=0x28ff1c; // hexideciaml
int a=10; //decimal (the most commonly used way)
int a=012177434; // octal
You may have some constants that are more easily understood when written in hexadecimal.
Bitflags, for example, in hexadecimal are compact and easily (for some values of easily) understood, since there's a direct correspondence 4 binary digits => 1 hex digit - for this reason, in general the hexadecimal representation is useful when you are doing bitwise operations (e.g. masking).
In a similar fashion, in several cases integers may be internally divided in some fields, for example often colors are represented as a 32 bit integer that goes like this: 0xAARRGGBB (or 0xAABBGGRR); also, IP addresses: each piece of IP in the dotted notation is two hexadecimal digits in the "32-bit integer" notation (usually in such cases unsigned integers are used to avoid messing with the sign bit).
In some code I'm working on at the moment, for each pixel in an image I have a single byte to use to store "accessory information"; since I have to store some flags and a small number, I use the least significant 4 bits to store the flags, the 4 most significant ones to store the number. Using hexadecimal notations it's immediate to write the appropriate masks and shifts: byte & 0x0f gives me the 4 LS bits for the flags, (byte & 0xf0)>>4 gives me the 4 MS bits (re-shifted in place).
I've never seen octal used for anything besides IOCCC and UNIX permissions masks (although in the last case they are actually useful, as you probably know if you ever used chmod); probably their inclusion in the language comes from the fact that C was initially developed as the language to write UNIX.
By default, integer literals are of type int, while hexadecimal literals are of type unsigned int or larger if unsigned int isn't large enough to hold the specified value. So, when assigning a hexadecimal literal to an int there's an implicit conversion (although it won't impact the performance, any decent compiler will perform the cast at compile time). Sorry, brainfart. I checked the standard right now, it goes like this:
decimal literals, without the u suffix, are always signed; their type is the smallest that can represent them between int, long int, long long int;
octal and hexadecimal literals without suffix, instead, may also be of unsigned type; their actual type is the smallest one that can represent the value between int, unsigned int, long int, unsigned long int, long long int, unsigned long long int.
(C++11, §2.14.2, ¶2 and Table 6)
The difference may be relevant for overload resolution1, but it's not particularly important when you are just assigning a literal to a variable. Still, keep in mind that you may have valid integer constants that are larger than an int, i.e. assignment to an int will result in signed integer overflow; anyhow, any decent compiler should be able to warn you in these cases.
Let's say that on our platform integers are in 2's complement representation, int is 16 bit wide and long is 32 bit wide; let's say we have an overloaded function like this:
void a(unsigned int i)
{
std::cout<<"unsigned";
}
void a(int i)
{
std::cout<<"signed";
}
Then, calling a(1) and a(0x1) will produce the same result (signed), but a(32768) will print signed and a(0x10000) will print unsigned.
It matters from a readability standpoint - which one you choose expresses your intention.
If you're treating the variable as an integral type, you know, like 2+2=4, you use the decimal representation. It's intuitive and straight-forward.
If you're using it as a bitmask, you can use hexa, octal or even binary. For example, you'll know
int a = 0xFF;
will have the last 8 bits set to 1. You'll know that
int a = 0xF0;
is (...)11110000, but you couldn't directly say the same thing about
int a = 240;
although they are equivalent. It just depends on what you use the numbers for.
well the truth is it doesn't matter if you want it on decimal, octal or hexadecimal its just a representation and for your information, numbers in computers are stored in binary(so they are just 0's and 1's) which you can use also to represent a number. so its just a matter of representation and readability.
NOTE:
Well in some of C++ debuggers(in my experience) I assigned a number as a decimal representation but in my debugger it is shown as hexadecimal.
It's similar to the assignment of and integer this way:
int a = int(5);
int b(6);
int c = 3;
it's all about preference, and when it breaks down you're just doing the same thing. Some might choose octal or hex to go along with their program that manipulates that type of data.

Another double type trick in C++?

First, I understand that the double type in C++ has been discussed lots of time, but I wasn't able to answer my question after searching. Any help or idea is highly appreciated.
The simplified version of my question is: I got three different results (a=-0.926909, a=-0.926947 and a=-0.926862) when I computed a=b-c+d with three different approaches and the same values of b, c and d, and I don't know which one to trust.
The detailed version of my question is:
I was recently writing a program (in C++ on Ubuntu 10.10) to handle some data. One function looks like this:
void calc() {
double a, b;
...
a = b - c + d; // c, d are global variables of double
...
}
When I was using GDB to debug the above code, during a call to calc(), I recorded the values of b, c and d before the statement a = b - c + d as follows:
b = 54.7231
c = 55.4051
d = -0.244947
After the statement a = b - c + d excuted, I found that a=-0.926909 instead of -0.926947 which is calculated by a calculator. Well, so far it is not quite confusing yet, as I guess this might just be a precision problem. Later on I re-implemented another version of calc() for some reason. Let's call this new version calc_new(). calc_new() is almost the same as calc(), except for how and where b, c and d are calculated:
void calc_new() {
double a, b;
...
a = b - c + d; // c, d are global variables of double
...
}
This time when I was debugging, the values of b, c and d before the statement a = b - c + d are the same as when calc() was debugged: b = 54.7231, c = 55.4051, d = -0.244947. However, this time after the statement a = b - c + d executed, I got a=-0.926862. That being said, I got three different a when I computed a = b - c + d with the same values of b, c and d. I think differences between a=-0.926862, a=-0.926909 and a=-0.926947 are not small, but I cannot figure out the cause. And which one is correct?
With Many Thanks,
Tom
If you expect the answer to be accurate in the 5th and 6th decimal place, you need to know exactly what the inputs to the calculation are in those places. You are seeing inputs with only 4 decimal places, you need to display their 5th and 6th place as well. Then I think you would see a comprehensible situation that matches your calculator to 6 decimal places. Double has more than sufficient precision for this job, there would only be precision problems here if you were taking the difference of two very similar numbers (you're not).
Edit: Unsurprisingly, increasing the display precision would have also shown you that calc() and calc_new() were supplying different inputs to the calculation. Credit to Mike Seymour and Dietmar Kuhl in the comments who were the first to see your actual problem.
Let me try to answer the question I suspect that you meant to ask. If I have mistaken your intent, then you can disregard the answer.
Suppose that I have the numbers u = 500.1 and v = 5.001, each to four decimal places of accuracy. What then is w = u + v? Answer, w = 505.101, but to four decimal places, it's w = 505.1.
Now consider x = w - u = 5.000, which should equal v, but doesn't quite.
If I only change the order of operations however, I can get x to equal v exactly, not by x = w - u or by x = (u + v) - u, but by x = v + (u - u).
Is that trivial? Yes, in my example, it is; but the same principle applies in your example, except that they aren't really decimal places but bits of precision.
In general, to maintain precision, if you have some floating-point numbers to sum, you should try to add the small ones together first, and only bring the larger ones into the sum later.
We're discussing here about smoke. If nothing changed in the environment an expression like:
a = b + c + d
MUST ALWAYS RETURN THE SAME VALUE IF INPUTS AREN'T CHANGED.
No rounding errors. No esoteric pragmas, nothing at all.
If you check your bank account today and tomorrow (and nothing changed in that time) I suspect you'll go crazy if you see something different. We're speaking about programs, not random number generators!!!
The correct one is -0.926947.
The differences you see are far too large for rounding errors (even in single precision) as one can check in this encoder.
When using the encoder, you need to enter them like this: -55.926909 (to account for the potential effect of the operator commutativity effects nicely described in previously submitted answers.) Additionally, a difference in just the last significant bit may well be due to rounding effects, but you will not see any with your values.
When using the tool, 64bit format (Binary64) corresponds to your implementation's double type.
Rational numbers do not always have a terminating expansion in a given base. 1/3rd cannot be expressed in a finite number of digits in base ten. In base 2, rational numbers with a denominator that is a power of two will have a terminating expansion. The rest won't. So 1/2, 1/4, 3/8, 7/16.... any number that looks like x/(2^n) can be represented accurately. That turns out to be a fairly sparse subset of the infinite series of rational numbers. Everything else will be subject to the errors introduced by trying to represent an infinite number of binary digits within a finite container.
But addition is commutative, right? Yes. But when you start introducing rounding errors things change a little. With a = b + c + d as an example, let's say that d cannot be expressed in a finite number of binary digits. Neither can c. So adding them together will give us some inaccurate value, which itself may also be incapable of being represented in a finite number of binary digits. So error on top of error. Then we add that value to b, which may also not be a terminating expansion in binary. So taking one inaccurate result and adding it to another inaccurate number results in another inaccurate number. And because we're throwing away precision at every step, we potentially break the symmetry of commutativity at each step.
There's a post I made: (Perl-related, but it's a universal topic) Re: Shocking Imprecision (PerlMonks), and of course the canonical What Every Computer Scientist Should Know About Floating Point Math, both which discuss the topic. The latter is far more detailed.