home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Journal 1990 - 1995 / CUJ.iso / mac / 1994.txt < prev    next >
Text File  |  1996-02-07  |  3MB  |  88,156 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78.  
  79.  
  80.  
  81.  
  82.  
  83.  
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90.  
  91.  
  92.  
  93.  
  94.  
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.  
  140.  
  141.  
  142.  
  143.  
  144.  
  145.  
  146.  
  147.  
  148.  
  149.  
  150.  
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214.  
  215.  
  216.  
  217.  
  218.  
  219.  
  220.  
  221.  
  222.  
  223.  
  224.  
  225.  
  226.  
  227.  
  228.  
  229.  
  230.  
  231.  
  232.  
  233.  
  234.  
  235.  
  236.  
  237.  
  238.  
  239.  
  240.  
  241.  
  242.  
  243.  
  244.  
  245.  
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272.  
  273.  
  274.  
  275.  
  276.  
  277.  
  278.  
  279.  
  280.  
  281.  
  282.  
  283.  
  284.  
  285.  
  286.  
  287.  
  288.  
  289.  
  290.  
  291.  
  292.  
  293.  
  294.  
  295.  
  296.  
  297.  
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.  
  306.  
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338.  
  339.  
  340.  
  341.  
  342.  
  343.  
  344.  
  345.  
  346.  
  347.  
  348.  
  349.  
  350.  
  351.  
  352.  
  353.  
  354.  
  355.  
  356.  
  357.  
  358.  
  359.  
  360.  
  361.  
  362.  
  363.  
  364.  
  365.  
  366.  
  367.  
  368.  
  369.  
  370.  
  371.  
  372.  
  373.  
  374.  
  375.  
  376.  
  377.  
  378.  
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404.  
  405.  
  406.  
  407.  
  408.  
  409.  
  410.  
  411.  
  412.  
  413.  
  414.  
  415.  
  416.  
  417.  
  418.  
  419.  
  420.  
  421.  
  422.  
  423.  
  424.  
  425.  
  426.  
  427.  
  428.  
  429.  
  430.  
  431.  
  432.  
  433.  
  434.  
  435.  
  436.  
  437.  
  438.  
  439.  
  440.  
  441.  
  442.  
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470.  
  471.  
  472.  
  473.  
  474.  
  475.  
  476.  
  477.  
  478.  
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.  
  536.  
  537.  
  538.  
  539.  
  540.  
  541.  
  542.  
  543.  
  544.  
  545.  
  546.  
  547.  
  548.  
  549.  
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562.  
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600.  
  601.  
  602.  
  603.  
  604.  
  605.  
  606.  
  607.  
  608.  
  609.  
  610.  
  611.  
  612.  
  613. A Short Floating- Point Type in C++
  614.  
  615.  
  616. William Smith
  617.  
  618.  
  619. William Smith is the engineering manager at Montana Software, a software
  620. development company specializing in custom applications for MS- DOS and
  621. Windows. You may contact him by mail at P.O. Box 663, Bozeman, MT 59771- 0663.
  622.  
  623.  
  624.  
  625.  
  626. Introduction
  627.  
  628.  
  629. Even though a typical microcomputer can have up to ten times the memory of one
  630. just a few years ago, there are still programming problems where memory is a
  631. limiting factor. I frequently bump into memory limitations in embedded and
  632. data acquisition applications. Numerous times I have had to work with a large
  633. quantity of floating- point numbers in a confining space. A common situation
  634. is the acquisition of large amounts of data through a 14- bit (or smaller) A-
  635. to- D (Analog to Digital) converter.
  636. Storing these numbers as 32-bit floats always seemed like overkill to me and a
  637. waste of space. This was especially annoying when I had to store tens of
  638. thousands of points in an array and would hit some kind of a memory limitation
  639. such as a segment boundary, physical memory limit, or even a file or disk size
  640. limit. The standard float type works, but it represents a poor match to the
  641. problem to be solved. Matching the floating- point size to what an application
  642. needs can result in significant memory savings in data- intensive programs.
  643. I really only needed a 16-bit floating- point type instead of the native
  644. 32-bit float. At first, I played some games and stored the data as short int.
  645. But this forced me to convert the data to float to do anything useful with it.
  646. I wanted a short floating-point type. I even implemented one, albeit crudely,
  647. in C. C allowed me to do it, but the conversion process never was clean or
  648. transparent. With C++, I was finally able to do what I wanted. I was able to
  649. create a short floating-point type that I could use naturally in my
  650. applications. C++ can hide all the dirty work, such as conversions.
  651. The new type, which I call sfloat, even allowed me to control range and
  652. precision. Some situations called for a floating-point type that ranged
  653. between 0 and 10.0 and maximized the precision within that range. Other
  654. situations required a larger signed range but less precision. Being able to
  655. tailor the characteristics of the type to meet an application's needs was a
  656. practical feature I built into sfloat,
  657. I implemented the sfloat type in "Standard C++" (if there is such a beast).
  658. The code works with Microsoft C++ and Borland C++ under MS-DOS and MS-Windows.
  659. It has some dependencies on the size of the standard types float, unsigned
  660. short int, and long. It assumes that:
  661. a float is 32 bits
  662. an unsigned short int is 16 bits
  663. a long is 32 bits
  664. It also assumes that the float type is that defined by the IEEE standard for
  665. 32-bit floating-point values. Table 1 gives the IEEE details. As long as a
  666. compiler and operating system conform to these restrictions, the code for
  667. sfloat will probably work in other environments.
  668.  
  669.  
  670. Implementation
  671.  
  672.  
  673. Listing 1, sfloat.hpp, defines a C++ class called sfloat. The class has
  674. numerous private static members, one protected member and numerous public
  675. member functions. There are even some non-member functions prototyped in
  676. sfloat.hpp.
  677. The static data provides a workspace for conversion between sfloat and float.
  678. This static data is class specific. All instances, or objects, of class sfloat
  679. share the same static data. The protected member s is the only object instance
  680. data. This member is unique to each instance of sfloat. In fact, the sizeof
  681. operator will report the size of sfloat to be the size of this member, 2
  682. bytes.
  683.  
  684.  
  685. Constructors
  686.  
  687.  
  688. One of the most elemental functions for a C++ class is the constructor. A
  689. constructor has the same function name as for the class. Furthermore, you can
  690. overload the constructor to provide construction from (conversion from)
  691. different types. The sfloat class has three constructors.
  692. sfloat();
  693. sfloat(float f);
  694. sfloat(sfloat& sf);
  695. sfloat() defines the "default" construction of an sfloat object, such as on
  696. the stack. The compiler would generate this function automatically if you do
  697. not specify it. sfloat(float f) converts a floating-point number to an sfloat
  698. to initalize the stored value. sfloat(sfloat& sf) initializes the new object
  699. by making a copy of another sfloat object. These three constructors provide
  700. the functionality needed to support the following declarations using sfloat.
  701. sfloat sf1;
  702. // uses sfloat();
  703. sfloat sf2 = 1.0f;
  704. // uses sfloat(float f);
  705. sfloat sf3 = sf2;
  706. // uses sfloat(sfloat& sf);
  707. These three types of construction and initialization cover the minimum
  708. required to use sfloat type naturally. The code for the constructor functions
  709. resides in Listing 2, sfloat.inl. sfloat() and sfloat(sfloat& sf) are very
  710. simple. On the other hand, sfloat(float f) has to do a bit of work. It has to
  711. convert a float to an unsigned short and assign it to the object instance data
  712. member s.
  713. The conversion process used in sfloat(float f) truncates the mantissa bits to
  714. a lower precision. It also lowers the range of the exponent by discarding
  715. higher-order bits. The conversion process utilizes some of the static data
  716. members of class sfloat as a work space and to hold intermediate values. The
  717. bitwise shift operators << and >> move the bits that will be kept from the
  718. float value into place before they are packed into an unsigned short.
  719. Since none of the constructor functions allocate memory on the heap (free
  720. store) using new there is no need to define a destructor function. C++ will
  721. provide a default destructor that does nothing.
  722.  
  723.  
  724. Conversion to float
  725.  
  726.  
  727. We also need a way to convert an sfloat object to a float. To use conventional
  728. notation, we need to define the operator function
  729. sfloat::operator float()
  730. Listing 2, sfloat. inl, contains the definition of this function. You will
  731. notice that it's logic is just the reverse of sfloat:: sfloat(float f). The
  732. shift operators once again move the bits of the sfloat into the proper
  733. locations in the 32 bits of a float. The extra bits are filled with zeros.
  734.  
  735.  
  736.  
  737. Overloaded Operators
  738.  
  739.  
  740. Operator overloading is one of the features of C++ that allow you to use new
  741. defined types just like the standard existing types. Operator overloading is
  742. not so much an object-oriented feature as a convenience. Table 2, an extract
  743. from Listing 1, lists the operator functions defined for sfloat. This list
  744. includes all the operators that one commonly uses on floating-point numbers.
  745. These operator functions allow you to use objects of the class sfloat just
  746. like you would a standard floating-point type.
  747. Operator overloading is fairly straight-forward feature of C++ and covered
  748. well elsewhere. I recommend the "Stepping Up To C++" series of articles on
  749. "Operator Overloading" by Dan Saks (see CUJ January, March, May, and July
  750. 1992). I took a very simple approach to implementing these operators. I
  751. convert to float, use the predefined operations, then convert back to sfloat.
  752. For example, here is the code for the add-assignment operator:
  753. inline sfloat &sfloat::
  754. operator+=(sfloat sf)
  755. {
  756. float f = (float)*this;
  757. f += (float)sf;
  758. *this = (sfloat)f;
  759. return ( *this );
  760. } // operator+=
  761. This techniques is not the most efficient (it has to do three type
  762. conversions), but it sure is simple. My needs for the sfloat type were
  763. data-size driven, not code-speed or code-size driven. Consequently I can live
  764. with the overhead of all those conversions. If you cannot, you could rewrite
  765. some of these routines to operate directly on the sfloat type.
  766. I would like to emphasize that you can get trapped into inefficienc