Applying C - Fixed Point Arithmetic
Written by Harry Fairhead   
Monday, 11 May 2020
Article Index
Applying C - Fixed Point Arithmetic
Rescaling
Printing Fixed Point

Printing Fixed Point

Finally, how do we print a fixed point value as a decimal?

This is more difficult than you might imagine and is often implemented incorrectly. You can get the integer part of the result simply by shifting:

temp>>8

and this can be printed as if it was just an integer, which is exactly what it is. You can also isolate the bits of the fractional part using a mask:

temp&0xFF

and at this point the temptation is to print this as if it was an int:

printf("%d.%d \n",temp>>8,temp&0xFF);

but it isn’t and this doesn’t work.

The reason is that the bit pattern is weighted by inverse powers of 2 and the bit pattern doesn’t correspond to the usual decimal values.

A simple example will illustrate the problem and give us the solution. Consider a fixed point value with the fractional part bit pattern:

10000000

which, if just treated as a decimal value, 128, gives a decimal fraction of:

.128

which is obviously wrong.

With the binary point inserted, the fractional part corresponds to:

0.10000000

and this is 0.5 in decimal, not 0.128.

The fractional part of the fixed point represents a value in the range 0 to less than 1, but as an unsigned binary integer it represents a range from 0 to 2s. We can use this to obtain a decimal representation. For example, for the binary fraction:

0.10000000

the integer representation is:

10000000

which is 128, and this corresponds to the decimal fraction:

128/28 = 128/256 = 1/2 = 0.5

Of course, we can’t do the division to get 0.5 because we only have integer arithmetic, but if we multiply by 1000, a power of ten sufficient to give an integer, then we can do the entire calculation using integer arithmetic:

1000*128/28 = 1000*128/256 = 500

which when printed with a decimal point in front is:

0.500

You can see that the power of ten gives you the corresponding number of decimal places.

Thus, if f is the fractional part converted to an integer, then 1000*f/2s is the decimal representation of the fraction.

To print the temperature we use:

printf("%d.%d \n",temp>>8,(temp&0xFF)*1000/(1<<8));

This works with obvious adjustments for any scale factor and any number of decimal places.

It is important to note that the multiplication has to be performed before the division and this introduces the possibility of overflow. The rule is that the number of decimal places, d, has to satisfy:

d*2s<232 or d<232-s

for a 32-bit int.

For example, if s is 16:

d<232-16<216<65536

the largest value of d that avoids an overflow is 10,000. If s is 8 then d can be as large as 10,000,000.

Omitted from this extract but in complete chapter:

  • Overflow During a Computation
  • Avoiding Overflow with 64-bits
  • Simulating 64-bit Multiply
  • GCC Fixed Point Extensions
  • Using a Fixed Point Library
  • Decimal Fixed Point
  • Some Speed Comparisons

Summary

  • Fixed-point arithmetic is just scaled integer arithmetic and is therefore simple and fast. However, modern floating point hardware can often match its speed.

  • You have to select the total number of bits and the number of bits to use as the binary fraction.

  • Fixed-point multiplication and division require rescaling to bring the binary point back to the original location.

  • Printing a fixed-point value is easy for the integer part, but the fractional part needs more care.

  • Because of the way the scaling works, fixed-point calculations can overflow, even though the final result can be represented in the given format. This can be avoided by working with more bits or by applying the rescaling during the calculation with the subsequent loss of precision.

  • There is no standard library for fixed point computation. GCC has some built-in functions, but these only work with specific hardware. An alternative that works with all hardware is libfixmath.

  • As well as using binary scaling in fixed point, you can also use decimal scaling. This is slower, but sometimes it is more direct.

  • It is worth remembering the fixed point doesn’t always have a speed advantage over hardware-implemented floating point. Always benchmark before making a choice.

 

 

Now available as a paperback or ebook from Amazon.

Applying C For The IoT With Linux

  1. C,IoT, POSIX & LINUX
  2. Kernel Mode, User Mode & Syscall
  3. Execution, Permissions & Systemd
    Extract Running Programs With Systemd
  4. Signals & Exceptions
    Extract  Signals
  5. Integer Arithmetic
  6. Fixed Point
    Extract Simple Fixed Point Arithmetic
  7. Floating Point
  8. File Descriptors
    Extract: Simple File Descriptors ***NEW
  9. The Pseudo-File System
    Extract: The Pseudo File System 
  10. Graphics
    Extract: framebuffer 
  11. Sockets
  12. Threading
    Extract  Condition Variables
    Extract  Deadline Scheduling
  13. Cores Atomics & Memory Management
  14. Interupts & Polling
  15. Assembler
    Extract: Assembler 

Also see the companion book: Fundamental C

<ASIN:1871962609>

<ASIN:1871962463>

<ASIN:1871962617>

<ASIN:1871962455>

Related Articles

Remote C/C++ Development With NetBeans

Raspberry Pi And The IoT In C

Getting Started With C/C++ On The Micro:bit

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on, Twitter, Facebook or Linkedin.

Banner


Developers Happier Working From Home
04/09/2020

Over half of developers are happier in their roles since the COVID-19 pandemic forced them to work remotely. The overwhelming majority are satisfied with their employers and at least three quarters an [ ... ]



Coursera Offers Free Access To Students
07/09/2020

Coursera has extended an offer it made earlier this year in response to the Covid-19 lockdown when universities in many parts of the world shut their campuses sent students home - free access to any o [ ... ]


More News

graphics

 



 

Comments




or email your comment to: comments@i-programmer.info



Last Updated ( Saturday, 16 May 2020 )