# Convert 2s complement to whole and fractional parts?

Discussion in 'Embedded Systems and Microcontrollers' started by spinnaker, Jan 24, 2015.

1. ### spinnaker Thread Starter AAC Fanatic!

Oct 29, 2009
5,699
2,201
I have a value in a buffer that represents a fractional 2s compliment number.

For example:
0000 0000 0000 1000 = +.05
0000 0000 1010 0010 = +10.125

I can convert them simple type setting a double to the buffer.

But I would like to avoid using floating point. I would like to break them into two separate integers.

.05
whole = 0
fraction = 5

10.25
whole=10
fraction=125

Or convert them to a string without using floating point

Any idea how to do this?

2. ### ErnieM AAC Fanatic!

Apr 24, 2011
7,907
1,789
Move the binary point in your calculations to avoid the fractional part.

That is equivalent to picking the units you work in, say using mA over amps. Note you are not limited to intervals of 3 in powers.

3. ### WBahn Moderator

Mar 31, 2012
20,247
5,758
I don't see how you can get +.05 in a fixed point system since that is 1/20 which is not even exactly representable in binary.

I have no idea what that last statement means. Could you give an example?

How is "fraction" of .05 equal to 5?

How is "fraction" of 10.25 equal to 125?

Don't you at least need a consistent denominator? In the first one your denominator is 100 and in the second it is 500.

What do you want in the string?

To get two integers, then you can do that by simple bit banging. To get the whole part just shift the value to the right equal to the number of fractional bits. To get the fractional part use a mask that has 0s to the left of the radix point and 1s to the right and then AND it with the original (there is another simple way to do it, too). The fractional part is the numerator with the denominator being 2^n where n is the number of fractional bits. If you want to convert that to, say, the numerator where the denominator is a power of ten, then multiply by the denominator you want and then right shift it by the number of fractional bits.

So let's assume there are four fractional bits and you want the result to be the numerator where the fraction is 1000.

Code (Text):
1.
2. 0000 0000 1010 0010  value
3. 0000 0000 0000 1010  whole = value >> 4
4.
5. 0000 0000 1010 0010  value
6. 0000 0000 0000 1111  mask
7. 0000 0000 0000 0010  frac = value & mask
8.
9. 0000 0111 1101 0000  frac *= 1000 (base 10)
10. 0000 0000 0111 1101  frac >>= 4
11.
whole = 10
frac = 125

4. ### spinnaker Thread Starter AAC Fanatic!

Oct 29, 2009
5,699
2,201

I did not think to put a whole number in an integer. That would work too. I would just need to output the location of the

Here is how I am converting now.

1f((value[1]) & 0xff == 0xff)
{
d = -(((~value[0]) +1) /2.0);
}
else
{
d = value[0];
d = (d / 2.0);
}
Seems to work for me as long as my values don't exceed 8 bits

What I wanted to return in a string, if the result was decimal point I guess.

Last edited: Jan 24, 2015
5. ### spinnaker Thread Starter AAC Fanatic!

Oct 29, 2009
5,699
2,201
These numbers are from the examples in the DS18B20 datasheet.

The one example makes sense

125 = 0000 0111 1101 0000

But the fractional ones are throwing me.

6. ### spinnaker Thread Starter AAC Fanatic!

Oct 29, 2009
5,699
2,201
Ah ok was not looking at the data sheet close enough. I did not see the little -1

I am guessing the is the fractional part of the number. I am going to look at the samples gain.

7. ### WBahn Moderator

Mar 31, 2012
20,247
5,758
Please use code tags and format your code. I'm assuming that that's an "if" on the first line, and not some function named "f()":

Code (Text):
1.
2. if((value[1]) & 0xff == 0xff)
3. {
4.   d = -(((~value[0]) +1) /2.0);
5. }
6. else
7. {
8.   d =  value[0];
9.   d = (d  / 2.0);
10. }
11.
What's value[1] and value[0]? We aren't mind readers!

You if() condition is only TRUE if the last four bits of value[1] are all 1s. Is that really what you want?

Why does a test on value[1] control what you do with value[0]? Again, we don't know what these two values are and how they relate to one another.

8. ### WBahn Moderator

Mar 31, 2012
20,247
5,758
Uh... yeah! That's what a fractional 2's complement representation means. It's also known as fixed point.

9. ### spinnaker Thread Starter AAC Fanatic!

Oct 29, 2009
5,699
2,201
The example

+10.125 = 0000 0000 1010 0010

Makes sense for the whole number part. 1010 = 10. I don't see where they are getting 125 out of the lower 4 bits.

Nor

0.5 = 0000 0000 0000 1000

10. ### WBahn Moderator

Mar 31, 2012
20,247
5,758
It would be nice if you linked the data sheet instead of making us search for it hoping to find the same one you are looking at.

http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf

When I look at page 4, I do not see the same numbers you posted. I see +0.5 (not +.05) and I see +10.125 (not +10.25, as you use in the second part of your OP).

11. ### MrChips Moderator

Oct 2, 2009
14,519
4,281
I wonder if you made a mistake here:
Here is what I would have expected:
You don't have to split it into whole numbers and fraction. What you have is called fixed point representation.
I very rarely use floating point arithmetic in embedded systems

12. ### WBahn Moderator

Mar 31, 2012
20,247
5,758
Did you look at the example where I worked through this?

The rightmost bit has a weighting of 2^-4 which is 1/16
The next bit has a weighting of 2^-3 which is 1/8
The next bit has a weighting of 2^-2 which is 1/4
The next bit has a weighting of 2^-1 which is 1/2

So 0010 in the last four is

0/2 + 0/4 + 1/8 + 0/16 = 1/8 = 0.125

And 1000 in the last four is

1/2 + 0/4 + 0/8 + 0/16 = 1/2 = 0.5

13. ### spinnaker Thread Starter AAC Fanatic!

Oct 29, 2009
5,699
2,201

Sorry having issues with copy and paste out of the pdf. And a hassle of transferring the numbers with one small screen

But I don't see how the fractional part works. Looking for fixed point info now, I know I have done this in the past long ago somewhere.

14. ### MrChips Moderator

Oct 2, 2009
14,519
4,281
Look at WBahn's post #12. That should be clear enough. If not, ask again.

15. ### spinnaker Thread Starter AAC Fanatic!

Oct 29, 2009
5,699
2,201

OK I get it now. So each bit in the fractional part actually represents a fraction.

So is there an easy way to convert that to a value I can display? I have some ideas of just checking if each bit is set and add 500, 250 etc. accordingly

So .5 = 500 + 0 + 0 = 500.

16. ### MrChips Moderator

Oct 2, 2009
14,519
4,281
Before we get into that, how many digits do you want to display? How many places after the decimal point?

Note that the value of the binary string taken as a whole is a decimal value that has been multiplied by 16.

Last edited: Jan 24, 2015
17. ### WBahn Moderator

Mar 31, 2012
20,247
5,758
The basic idea behind a fixed point system can be view at from two different -- and equivalent -- perspectives. The first is that you have a radix point (or binary point, which serves the exact same purpose as a decimal point, namely separating the whole part from the fractional part). The second is that you take a real number and scale it so that the fractional information you want is contained in the whole part and then you do all of your work with the integers.

For instance, in banking it is quite common to only work with integers to represent dollar amounts in cents. This is accomplished simply by multiplying all money amounts, such as \$1.98, by 100 so that you are working with 198 (note: they scale it up more, but this gets the idea across). You can then work with integers and, at the end, simply divide by 100 to get things back.

For a binary fixed point system you multiply by powers of two. Just as multiplying by ten in a decimal system moves the decimal point one place to the right, multiplying by two in a binary system moves the radix point one bit to the right.

So take a value like 10.125 and multiply it by 16 (four places) and you get 162. What is the binary representation of the integer 162? Compare that to the entry for 10.125 in the data sheet.

18. ### WBahn Moderator

Mar 31, 2012
20,247
5,758
I showed you how to do that (for three decimal places) in detail in Post #3.

If you want two places, then multiply by 100. If you want four places, then multiply by 10000. If you want N places, then multiply by 10^N.

There are other ways to do it as well, depending on how you are converting integers to strings.

19. ### MrChips Moderator

Oct 2, 2009
14,519
4,281
WBahn and I are cross posting. But we are both showing you the same thing.
If you want to display two decimal places, multiply the number by 100 and divide by 16.
All you have to do is display the result and insert decimal point before the last two digits.
If you want to implement rounding correctly I will show you how to do that.

20. ### spinnaker Thread Starter AAC Fanatic!

Oct 29, 2009
5,699
2,201

Ah OK I see it now. The table thing through me a little. Wow that is easy! Thanks for the help and sorry for being so dense. I will blame it on the beer.