Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Database

Decimal Fractional Conversion


AUG91: DECIMAL FRACTIONAL CONVERSION

Don is a consulting engineer specializing in embedded systems. He can be contacted at Pacific Precision Laboratories in Chatsworth, Calif., or at Don Morgan Electronics, 2669 N. Wanda, Simi Valley, CA 93065.


More often than not, writing code for an embedded system means looking for a balance of speed and storage. When the system must process numerical data, this can become critical, arithmetic takes time. There are any number of solutions that might be implemented, such as sticking to integer only arithmetic, or going to fixed point if fractional calculations are necessary. Even then, systems that must relate to humans for numerical data often receive it in decimal form, and because decimal arithmetic is not native to most processors, what follows is some form of radix conversion. Good front-end routines can make a difference in speed, storage requirements, and accuracy and the 8086 provides some tools to aid in this effort.

Common Conversion Methods

Tables are commonly used for conversions between one "kind" of thing to another, such as rpm to cycles, pounds to stone, feet to millimeters. They are useful for converting between bases, too. However, they require more space and are slower than necessary, and they do not accommodate fractional parts particularly well.

Another common method is to perform a straightforward integer conversion, keeping track of the decimal places for fractional parts so that a final divide can be done to bring the result back into range. This is a common solution but requires the program to keep track of the radix point and does not readily produce fractional parts native to the hardware of an embedded system, such as D/A converters.

There is another approach that works well on processors that provide instructions for doing decimal adjustments--the 8086, for instance--that is faster than the table-driven method and produces true binary fractions for either fast, fixed point routines or hardware.

Fractional Parts

The code fragment in Example 1 provides an interesting example of radix conversion performed by multiplying the input value by the target base, using the arithmetic of the base being converted from. In this case, where the target is binary and the convert-from base is decimal, the conversion is accomplished using simple additions and the DAA instruction.

After the input has been buffered, the numbers following the radix point are packed and placed in an accumulator concatenated with a result variable to hold the converted mantissa. The number in the accumulator is added to itself to perform a multiply by two and take advantage of the AF flag. All standard carries are allowed to occur and overflow into the concatenated register meant to hold the mantissa. Each addition is followed by the DAA instruction to handle the additional interdigital carries that can occur with a decimal overflow. This conversion can continue until the accumulator is exhausted or the desired precision is reached. In addition to being fast, this method can produce higher accuracy than the table method just mentioned.

The Conversion Routines

The code in Example 1 was written for an embedded system using fixed point arithmetic to perform high-speed calculations in a real-time control application. It expected values ranging from .00002 to 50,000, a range that allowed both integer and mantissa to share a doubleword (32 bits) with the radix point between the two words. This routine can be rewritten, however, to accommodate data of any size.

Before calling the subroutine, the fractional portion is packed and stored in DEC_FRAC. The FRAC subroutine is called with AX already loaded with the packed fraction still in decimal notation. Upon entry, CX is set to the number of bits in the resulting mantissa; this tells the routine when it is at the needed precision. Each byte is multiplied by two through addition (NOT SHIFTED) in order to use the Auxiliary Flag as well as the standard Carry. Following each addition, the DAA instruction is executed to handle decimal overflows, with the carry flag being checked, as well, to handle normal carries. Both types of overflow are handled to maintain decimal arithmetic. At the end of this routine, the remainder still in AX is checked and the fraction in DX is rounded up if necessary. The result is placed in MANTISSA.

Conclusion

A routine of this sort can be useful, as it does without the ROM or RAM storage required of a table-driven routine. Even more interesting, though, is its ability to produce a binary fractional conversion with accuracy and speed.

Example 1: Fractional conversion routine

  mantissa  word  ?
  dec_frac word   ?
  ;
  ; frac-conversion of decimal fractional part to hex
  ; enter with packed decimal word in ax
  ; returns with result in dx\
  ;DS is assumed to point into the Data Segment
  ;
  frac   proc
     mov cx,10h    ;number of bits in resulting mantissa
  cnvt:
     add al,al     ;could add to self, we will see
     daa
     mov bl,al
     mov al,ah
     jnc nc1
     add al,al     ;could add to self, we will see
     daa
     inc al
     jmp short nc2
  nc1:
     add al,al     ;could add to self, we will see
     daa
  nc2:
     mov ah,al
     mov al,bl
     rcl dx,1
     loop    cnvt
     sub ax, 5000h
     jc  end_frac
     inc dx    ;for round off
  end_frac:
     mov word ptr mantissa, dx
     ret
  frac   end


Copyright © 1991, Dr. Dobb's Journal


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.