# Create Fixed-Point Data

This example shows the basics of how to use the fixed-point numeric object `fi`

.

The fixed-point numeric object is called `fi`

because J.H. Wilkinson used `fi`

to denote fixed-point computations in his classic texts Rounding Errors in Algebraic Processes (1963), and The Algebraic Eigenvalue Problem (1965).

### Setup

This example may use display settings or preferences that are different from what you are currently using. To ensure that your current display settings and preferences are not changed by running this example, the example automatically saves and restores them. The following code captures the current states for any display settings or properties that the example changes.

originalFormat = get(0,'format'); format loose format long g

Capture the current state of and reset the `fi`

display and logging preferences to the default values.

fiprefAtStartOfThisExample = get(fipref); reset(fipref);

### Create Fixed-Point Number with Default Properties

To assign a fixed-point data type to a number or variable with the default fixed-point properties, use the `fi`

constructor. The resulting fixed-point value is called a `fi`

object.

For example, create `fi`

objects `a`

and `b`

. The first input to the `fi`

constructor is the value.

a = fi(pi)

a = 3.1416015625 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 13

b = fi(0.1)

b = 0.0999984741210938 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 18

The default fixed-point attributes are displayed. You can specify these attributes when you construct `fi`

variables.

The default `WordLength`

is 16 bits. When the `FractionLength`

property is not specified, it is automatically set to the fraction length that gives the best precision for the given word length while avoiding an overflow, keeping the most-significant bits of the value.

### Specify Signedness and Word Length Properties

The second and third inputs to the `fi`

constructor specify signedness and the word length in bits, respectively.

Create a signed 8-bit `fi`

object.

a = fi(pi,1,8)

a = 3.15625 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 8 FractionLength: 5

Create an unsigned 20-bit `fi`

object.

b = fi(exp(1),0,20)

b = 2.71828079223633 DataTypeMode: Fixed-point: binary point scaling Signedness: Unsigned WordLength: 20 FractionLength: 18

### Precision

The data is stored internally with as much precision as is specified. However, initializing high precision fixed-point variables with double-precision floating-point variables may not give the resolution you might expect at first glance.

For example, initialize an unsigned 100-bit fixed-point variable with a value of 0.1 and then examine its binary expansion.

a = fi(0.1,0,100)

a = 0.1 DataTypeMode: Fixed-point: binary point scaling Signedness: Unsigned WordLength: 100 FractionLength: 103

bin(a)

ans = '1100110011001100110011001100110011001100110011001101000000000000000000000000000000000000000000000000'

The infinite repeating binary expansion of 0.1 gets cut off at the 52nd bit. The 53rd bit is significant and it is rounded up into the 52nd bit. This is because double-precision floating-point variables (the default MATLAB® data type), are stored in 64-bit floating-point format, with 1 bit for the sign, 11 bits for the exponent, and 52 bits for the mantissa plus one hidden bit. This results in an effective 53 bits of precision. Even though double-precision floating-point has a very large range, its precision is limited to 53 bits. For more information on floating-point arithmetic, refer to Chapter 1 Numerical Computing with MATLAB, by Cleve Moler.

Because most fixed-point processors have data stored in a smaller precision, and then compute with larger precisions, you may want to create a `fi`

object that has more precision than double-precision floating point.

For example, initialize a 40-bit unsigned `fi`

and multiply using full-precision for products. The full-precision product of 40-bit operands is 80 bits, which is greater precision than standard double-precision floating-point.

a = fi(0.1,0,40); bin(a)

ans = '1100110011001100110011001100110011001101'

b = a*a

b = 0.0100000000000045 DataTypeMode: Fixed-point: binary point scaling Signedness: Unsigned WordLength: 80 FractionLength: 86

bin(b)

ans = '10100011110101110000101000111101011100001111010111000010100011110101110000101001'

### Access Data

The data can be accessed in a number of ways which map to built-in data types and binary strings.

For example, `double(a)`

returns the double-precision floating-point real-world value of `a`

, quantized to the precision of `a`

.

a = fi(pi); double(a)

ans = 3.1416015625

You can also set the real-world value in a double. For example, set the real-world value of `a`

to `e`

, quantized to the numeric type of `a`

.

a.double = exp(1)

a = 2.71826171875 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 13

Use the `storedInteger`

function to return the stored integer in the smallest built-in integer type available, up to 64 bits.

storedInteger(a)

`ans = `*int16*
22268

### Relationship Between Stored Integer Value and Real-World Value

In binary-point scaling, the relationship between the stored integer value and the real-world value is

$$\text{Real}\text{-}\text{world}\text{}\text{value}=(\text{Stored}\text{}\text{integer})\cdot {2}^{-\text{Fraction}\text{}\text{length}}.$$

There is also slope-bias scaling, which has the relationship

$$\text{Real}\text{-}\text{world}\text{}\text{value}=(\text{Stored}\text{}\text{integer})\cdot \text{Slope}+\text{Bias}$$

where

$$\text{Slope}=(\text{Slope}\text{}\text{adjustment}\text{}\text{factor})\cdot {2}^{\text{Fixed}\text{}\text{exponent}}.$$

and

$$\text{Fixed}\text{}\text{exponent}=-\text{Fraction}\text{}\text{length}.$$

The math operators of `fi`

work with binary-point scaling and real-valued slope-bias scaled `fi`

objects.

### Other Data Formats

The functions `bin`

, `oct`

, `dec`

, and `hex`

return the stored integer in binary, octal, unsigned decimal, and hexadecimal strings, respectively.

bin(a)

ans = '0101011011111100'

oct(a)

ans = '053374'

dec(a)

ans = '22268'

hex(a)

ans = '56fc'

You can use dot notation to set the stored integer from binary, octal, unsigned decimal, and hexadecimal strings.

$$\text{fi}(\pi )$$

`a.bin = '0110010010001000'`

a = 3.1416015625 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 13

$$\text{fi}(\varphi )$$

`a.oct = '031707'`

a = 1.6180419921875 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 13

$$\text{fi}(e)$$

`a.dec = '22268'`

a = 2.71826171875 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 13

$$\text{fi}(0.1)$$

`a.hex = '0333'`

a = 0.0999755859375 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 13

### Specify Fraction Length

When the `FractionLength`

property is not specified, it is computed to give the best precision for the magnitude of the value and given word length, while avoiding overflow. You may also specify the fraction length directly as the fourth numeric argument in the `fi`

constructor.

Compare the fraction length of `a`

, which was explicitly set to 0, to the fraction length of `b`

, which was set to best precision for the magnitude of the value.

a = fi(10,1,16,0)

a = 10 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 0

b = fi(10,1,16)

b = 10 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 11

The stored integer values of `a`

and `b`

are different, even though their real-world values are the same. This is because the real-world value of `a`

is the stored integer scaled by 2^0 = 1, while the real-world value of `b`

is the stored integer scaled by 2^-11 = 0.00048828125.

storedInteger(a)

`ans = `*int16*
10

storedInteger(b)

`ans = `*int16*
20480

### Specify Properties with Name-Value Pair Arguments

You can specify the numeric type properties by passing numeric arguments to the `fi`

constructor, as shown above. You can also specify properties by giving the name of the property as a string followed by the value of the property.

`a = fi(pi,'WordLength',20)`

a = 3.14159393310547 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 20 FractionLength: 17

### Numeric Type Properties

Each `fi`

object has an associated `numerictype`

object. The `numerictype`

object stores information about the `fi`

object, including word length, fractionlength, and signedness.

T = numerictype

T = DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 15

The numeric type properties can be modified either when the object is created by passing in name-value pair arguments.

T = numerictype('WordLength',40,'FractionLength',37)

T = DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 40 FractionLength: 37

You can also assign numeric type properties by using the dot notation.

T.Signed = false

T = DataTypeMode: Fixed-point: binary point scaling Signedness: Unsigned WordLength: 40 FractionLength: 37

All of the numeric type properties of a `fi`

may be set at once by passing in the `numerictype`

object. This allows you to, for example, create multiple `fi`

objects that share the same numeric type properties.

`a = fi(pi,'numerictype',T)`

a = 3.14159265359194 DataTypeMode: Fixed-point: binary point scaling Signedness: Unsigned WordLength: 40 FractionLength: 37

`b = fi(exp(1),'numerictype',T)`

b = 2.71828182845638 DataTypeMode: Fixed-point: binary point scaling Signedness: Unsigned WordLength: 40 FractionLength: 37

You can also pass the `numerictype`

object directly to the `fi`

constructor.

a1 = fi(pi,T)

a1 = 3.14159265359194 DataTypeMode: Fixed-point: binary point scaling Signedness: Unsigned WordLength: 40 FractionLength: 37

### Display of Real-World Values

When displaying real-world values, the closest double-precision floating-point value is shown. Double-precision floating-point may not always be able to represent the exact value of high-precision fixed-point numbers. For example, an 8-bit fractional number can be represented exactly in doubles.

a = fi(1,1,8,7)

a = 0.9921875 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 8 FractionLength: 7

bin(a)

ans = '01111111'

A 100-bit fractional number cannot be exactly represented.

b = fi(1,1,100,99)

b = 1 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 100 FractionLength: 99

The output displays `1`

when the exact value is `1 - 2^-99`

.

However, that the full precision is preserved in the internal representation of `fi`

.

bin(b)

ans = '0111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111'

### Display Preferences

Use the `fipref`

object to set the display preferences for `fi`

. Use the `savefipref`

function to save display preferences between MATLAB sessions.

The display of the `fi`

object is also affected by the `format`

function. When displaying real-world values, you can use

format long g

so that as much precision will be displayed as possible.

### Cleanup

Set any display settings or preferences that the example changed back to their original states.

fipref(fiprefAtStartOfThisExample); set(0,'format',originalFormat); %#ok<*NOPTS,*NASGU>

## See Also

`fi`

| `fipref`

| `savefipref`

| `numerictype`

| `storedInteger`

| `bin`

| `oct`

| `dec`

| `hex`