Fixed Point Numbers

In Ada 95 and later, yes, but for some reason Ada 95 wasn’t available in 1984.

2 Likes

Ah, I forgot that digits was 95 addition.

In (most, if not all) modern machines the scale of a fixed-point number is a construct in the mind of the programmer. What you have are plain old integers, and you might choose to interpret the LSB as having value 0.1 (1/10) say, or 0.0625 (1/16). If you multiply one of each together, you’ll get a (double-length) product where the LSB has value 1/160. Most of the pain of fixed-point multiplication is working out how you want to deal with that product; of division, how you want to present the dividend to the machine’s divide hardware to get the result you need.

1 Like

But you cannot multiply values of two different fixed-point types anyway.

But in any case the point stands. If your scale is a power of the machine radix you can implement fixed-point multiplication and division using shifts in that radix.

Oh yes you can. You “merely” have to deal with the scaling of the result.

with Ada.Text_IO; use Ada.Text_IO;
procedure Fixed is
   type Dec is delta 0.1 range 0.0 .. 5.0 with
     Small => 0.1;
   type Fix is delta 0.1 range 0.0 .. 5.0;
   Product_Delta : constant := Dec'Small * Fix'Small;
   type Product is delta Product_Delta range 0.0 .. 25.0 with
     Small => Product_Delta;
   Half_Product_Delta : constant := Product_Delta / 2.0;
   type Short_Product is delta Half_Product_Delta range 0.0 .. 25.0 with
     Small => Half_Product_Delta;
   D : Dec := 0.7;
   F : Fix := 0.7;
begin
   Put_Line (Product'(D * F)'Image);
   Put_Line (Short_Product'(D * F)'Image);
end Fixed;

Both outputs are 0.481 (obviously should be 0.49, but it’s that F’(0.7)).

In the example I gave above, the compiler can generate the Product result by taking the unaltered output of the multiplication. To generate the Half_Product result it would have to shift the output up one place. If you decided to assign the result to a type with a ’Small that wasn’t a binary multiple, say Product_Delta / 3.0, the compiler would have to scale the result to match (in that case, multiplying the multiplication’s output by 3).

1 Like

OK, I get universal_fixed which is a rational number.

Compare code generated for decimal and binary fixed-point:

   type Dec is delta 0.1 digits 2 range 0.0 .. 5.0;
   type Fix is delta 0.1 range 0.0 .. 5.0;

   D : Dec := 0.7;
   F : Fix := 0.7;
begin
   D := D * D;
   F := F * F;

You need a lot more for the decimal one because the machine radix is 2.