MATLAB Answers

Extracting first 8 bit from fixed point number

10 views (last 30 days)
Lennart
Lennart on 24 Jun 2015
Answered: Andy Bartlett on 5 Apr 2021
Hi there,
I am currently having trouble with the above mentioned task. Basically, this is what I want to do:
x = fi(1300,true,11,0) (9bit signed integer)
x.bin = 10100010100
c = fi(0,true,8,0)
c = x.bin(1:8)
c.bin = 10100010
c = 162
In other words: I would like to extract the first 8 bit of x to another variable, which than will have the according value. Does the fixed point toolbox has any function that makes this possible. Everything I tried so far ended up in a requantization of the value, which I don't want.
Any help would be highly appreciated!
Thank you very much!
Regards,
Lennart
  1 Comment
Lennart
Lennart on 29 Jun 2015
Giving this a little push upwards. Is there really no function that can do that?

Sign in to comment.

Accepted Answer

Walter Roberson
Walter Roberson on 29 Jun 2015
  1 Comment
Lennart
Lennart on 29 Jun 2015
One problem I have left with the function. The result is an unsigned variable and again: I can not change it to a signed variable without having matlab recasting the variable and do crazy stuff ...
Any suggestions would be highly appreciated!
Regards,
Lennart

Sign in to comment.

More Answers (2)

Lennart
Lennart on 29 Jun 2015
There we go. Thank you so much for this. Works perfectly!

Andy Bartlett
Andy Bartlett on 5 Apr 2021
Two Key Ways
There are two key ways to extract the bits from a fixed-point number.
One way is to use bitsliceget as Walter pointed out.
The other way is to do a cast operation configured for overflows to wrap and rounding toward floor.
Consider the following input value.
a = fi( -5.0625, 1, 8, 4)
The bits of a are the following.
'10101111'
Suppose the goal is to extract the 6 most significant bits from a. This can be done with bitsliceget as follows.
b = bitsliceget( a, 8, 3 )
or using fi to do a cast.
fmWrapFloor = fimath('RoundingMethod', 'Floor', 'OverflowAction', 'Wrap');
c = fi( a, 1, 6, 2, fmWrapFloor )
Both approaches produce the same set of bits in their outputs.
'101011'
But the outputs have different data types and different real world values.
Term bin_SI type RealWorldValue
a 10101111 numerictype(1,8,4) -5.0625
bitsliceget( a, 8, 3 ) 101011 numerictype(0,6,0) 43
fi( a, 1, 6, 2, fmWrapFloor ) 101011 numerictype(1,6,2) -5.25
Using bitsliceget returns the stored integer bits in an unsigned type with no scaling.
Casting using fi will retain the scaling appropriate to the bits. Signedness can be kept or discared as desired. Casting via fi will also attempt to keep the output real world value close to the input real world value to the extent allowed by rounding and overflow. Notice in the example above that the input real world value is -5.0625 and after dropping the least significant two bits the output is rounded to real world value -5.25.
Randomly generated examples
The attached script randomly creates some examples showing the differences. For a example, one run produced this random output examples.
>> example_bitslice
Term bin_SI type RealWorldValue
a 00001110 numerictype(1,8,4) 0.875
bitsliceget( a, 8, 2 ) 0000111 numerictype(0,7,0) 7
bitsliceget( a, 8, 3 ) 000011 numerictype(0,6,0) 3
bitsliceget( a, 8, 4 ) 00001 numerictype(0,5,0) 1
bitsliceget( a, 6, 1 ) 001110 numerictype(0,6,0) 14
bitsliceget( a, 6, 3 ) 0011 numerictype(0,4,0) 3
bitsliceget( a, 3, 1 ) 110 numerictype(0,3,0) 6
Term bin_SI type RealWorldValue
a 00001110 numerictype(1,8,4) 0.875
fi( a, 1, 7, 3, fmWrapFloor ) 0000111 numerictype(1,7,3) 0.875
fi( a, 1, 6, 2, fmWrapFloor ) 000011 numerictype(1,6,2) 0.75
fi( a, 1, 5, 1, fmWrapFloor ) 00001 numerictype(1,5,1) 0.5
fi( a, 1, 6, 4, fmWrapFloor ) 001110 numerictype(1,6,4) 0.875
fi( a, 1, 4, 2, fmWrapFloor ) 0011 numerictype(1,4,2) 0.75
fi( a, 1, 3, 4, fmWrapFloor ) 110 numerictype(1,3,4) -0.125
Term bin_SI type RealWorldValue
a 10101111 numerictype(1,8,4) -5.0625
bitsliceget( a, 8, 2 ) 1010111 numerictype(0,7,0) 87
bitsliceget( a, 8, 3 ) 101011 numerictype(0,6,0) 43
bitsliceget( a, 8, 4 ) 10101 numerictype(0,5,0) 21
bitsliceget( a, 6, 1 ) 101111 numerictype(0,6,0) 47
bitsliceget( a, 6, 3 ) 1011 numerictype(0,4,0) 11
bitsliceget( a, 3, 1 ) 111 numerictype(0,3,0) 7
Term bin_SI type RealWorldValue
a 10101111 numerictype(1,8,4) -5.0625
fi( a, 1, 7, 3, fmWrapFloor ) 1010111 numerictype(1,7,3) -5.125
fi( a, 1, 6, 2, fmWrapFloor ) 101011 numerictype(1,6,2) -5.25
fi( a, 1, 5, 1, fmWrapFloor ) 10101 numerictype(1,5,1) -5.5
fi( a, 1, 6, 4, fmWrapFloor ) 101111 numerictype(1,6,4) -1.0625
fi( a, 1, 4, 2, fmWrapFloor ) 1011 numerictype(1,4,2) -1.25
fi( a, 1, 3, 4, fmWrapFloor ) 111 numerictype(1,3,4) -0.0625
Which approach to use?
Sometimes the intent of a design section is bit oriented. For example, a collection of bits may represent several independent boolean flags. The design intent may be to pack and unpack these bits in to a larger variable. In this case, bitsliceget is a more natural fit to the design intent.
Other times, the intent is oriented towards math operations. As an example, suppose a variable represents the output from an angle sensor with units being revolutions. To efficiently compute trig operations, like cosine, on this variable, it is useful to perform a modulo operation so that the angle is in the closed open interval [0,1). A great advantage to using revolutions, instead of degrees or radians, is that this modulo can be performed by simply dropping all the bits to the left of the variables binary point. Extracting the bits to the right of the binary point could be done with bitsliceget but the scaling would be lost and the real world value of the output would no longer be revolutions. In contrast, casting via fi would preserve the wrapped real world value in revolutions. For math oriented intent, extracting bit using a wrapping floor fi cast is usually a more natural fit.
uAngleRevolutions = fi( 3.2470703125, 0, 16, 10 )
fmWrapFloor = fimath('RoundingMethod', 'Floor', 'OverflowAction', 'Wrap');
modOne_of_uAngleRevolutions = fi( uAngleRevolutions, 0, 10, 10, fmWrapFloor );
modOne_of_uAngleRevolutions = removefimath( modOne_of_uAngleRevolutions )
This outputs
uAngleRevolutions =
3.2470703125
numerictype(0,16,10)
modOne_of_uAngleRevolutions =
0.2470703125
numerictype(0,10,10)
The original angle is three full revolutions around the circle plus roughly an additional quarter revolution. Modulo one of this angle is just the roughly quarter revolution around the circle. Using a wrapping fi cast, performed the module one operation and nicely preserved the real world meaning.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!