'Print the last rad in while loop in Ada
I wrote a program in Ada that ask user to put startprise, stopppris,step and procent, the the program will calculate and print the result.
My code is good,I have no problem with it, I can print all values except the last row.
The user will tell Folowing values:
Startprise:10.0
stopprise: 11.0
Step: 0.1
Procent: 10.0
The result should be like:
10.00 1.00 11.00
10.10 1.01 11.11
----etc
10.90 1.09 11.99
11.00 1.10 12.10
My code cann,t print the last row, while loop stop at 10.90 1.09 11.99, how I can fix it and print the last row:
enter code here
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;
procedure Main is
startpris, stoppris,step:Float := 0.0 ;
procent: Float := -0.1;
priseftermoms, moms: Float;
p : Float := 100.0;
I : Integer:= 1;
J : Float := 0.0;
x : Float := -0.1;
index: Float := 0.0;
begin
while startpris <= J loop
Put("Första Pris: ");
Get(startpris);
if startpris < J then
Put_Line (" Felaktigt värde!");
end if;
end loop;
while stoppris <= J or stoppris <= startpris loop
Put("Sista Pris: ");
Get(stoppris);
--stoppris := Float'Value(Get_Line);
if startpris > stoppris then
Put_Line ("Felaktigt värde!");
end if;
end loop;
while step <= J loop
Put("Steg: ");
Get(step);
--step := Float'Value (Get_Line);
if step < J then
Put_Line (" Felaktigt värde!");
end if;
end loop;
while procent < J or procent > p loop
Put("Momsprocent: ");
Get(procent);
if procent <= x then
Put_Line (" Felaktigt värde!");
end if;
if procent > P then
Put_Line (" Felaktigt värde!");
end if;
end loop;
Put_Line("");
Put_Line("=================== Momstabell =====================");
Put_Line("Pris utan moms Moms Pris med moms");
while stoppris >= startpris loop
moms := (startpris * procent)/ p;
priseftermoms := moms + startpris;
put(startpris,fore=>1, aft => 2, exp=> 0);
put(" ");
put(moms,fore=>1, aft => 2, exp=> 0);
put(" ");
put(priseftermoms,fore=>1, aft => 2,exp=> 0);
Put_Line("");
startpris := startpris + step;
end loop;
end Main;
Solution 1:[1]
Your mistake is in thinking that computation with floating-point numbers (type Float) is exactly the same as computing with base-10 numbers with decimal parts. In a binary computer, floating-point numbers are represented in binary, base 2, which means that fractions such as 1/10, although written as 0.1 in the source code and in input text, are not represented exactly but with a small error that depends on the number of bits in the mantissa. So the program is actually computing with a value that is either 0.099...9x..., where the digit x is not 9, or 0.100...0x..., where the digit x is not zero. That is, the value in the computations is either slightly less than 0.1 or slightly more than 0.1.
This means that in your program, as the last while-loop adds "step" to "startpris", there is both an initial error (from the conversion of the input base-10 numbers into binary numbers) and a cumulative error (from the repeated addition of "step", with its initial error). The result is that after N iterations, the value of "startpris" is not exactly 10.0 + N*0.1, but something slightly different. So after 10 iterations, when you expect the loop to print out the values for "startpris" = 110.0, it may happen (and seems to happen) that the actual value of "startpris" is a little larger than 110.0. The while-loop condition is then False, and the loop is not executed for that value of "startpris".
To correct the program, you can either make the while-loop condition tolerant of this small error, for example as
while stoppris >= startpris - step/2.0 loop
or you can compute the integer number of steps that are needed, and then loop for that number of steps, for example as
steps : constant Natural := Natural ((stoppris - startpris) / step);
pris : Float;
...
for num_step in 0 .. steps loop
pris := startpris + Float(num_step) * step;
moms := (pris * procent) / p;
... and so on, using "pris" instead of "startpris".
Note that the conversion to Natural in the declaration of "steps" rounds the floating-point number to the nearest integer. This makes it tolerant to the small errors in the binary floating-point representation.
I recommend this second method, computing the number of steps and then using a for-loop.
There is a third solution, which is apt when dealing with amounts where the number of decimals is fixed, for example euros and cents written as xxx.yy, where yy is the number of cents. Then you can use the "decimal fixed-point types" of Ada to get exact calculations in base 10 with two decimals. But that is too long a subject for an SO answer...
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
