Invalid Floating Point Operation? - pascal

I am a beginner in Pascal. I made this simple calculating program and keep getting exitcode : 207 message when running this code. Some website says that it is because of the invalid floating point operation. So I suppose its because of the division of zero. But I don't know how to avoid that.
uses crt;
var
a, b, c, d, e, f : real;
begin
c := a + b;
d := a - b;
e := a * b;
f := a / b;
writeln(' Basic Math Operation ');
writeln('Write First Number a ');
readln(a);
writeln('Write Second Number b ');
readln(b);
writeln('The addition of a + b =', c);
writeln('The substraction of a - b =', d);
writeln('The multiplication of a x b =', e);
writeln('The division of a / b =', f);
readln;
end.
I also tried to add this but keep getting the same exitcode : 207
if (b=0) then
writeln(' Can't do division by 0 !')
else
writeln('The division of a / b =', f);
or this one that i found on a forum
except on EDivByZero do ShowMessage('Can't do division by 0 !');
What shall i do???

Assuming you are using Free Pascal:
By default, simple variables in Pascal are not initialized after their declaration. Any assumption that they contain 0 or any other default value is erroneous: They can contain rubbish. To remedy this, the concept of initialized variables exists. The difference with normal variables is that their declaration includes an initial value, as can be seen in the diagram in the previous section.
Remark 2 exceptions to this rule exist:
Managed types are an exception to this rule: Managed types are always initialized with a default value: in general this means setting the reference count to zero, or setting the pointer value of the type to Nil. See section 3.9, page 226
Global variables are initialized with the equivalent of zero.
a, b, c, d are initialised to 0 at the start of the program. Therefore f:=a/b produces division by zero error. You should move the line readln(a) and readln(b) at the start of the program to assign a value to the variables before use. Also check whether b is inputted as 0 to avoid similar issues.

Related

Division by 0 in TurboPascal7

I am working on my school project and I am (almost) furious about this issue. My solution's validity is 95 %, but I have 1 input wrong – I don't know the input, but I know, that the input failed because of the error code 200, which is divison by 0.
My project is this:
„The digit sum of an integer is defined to be the sum of the digits in the integer's written form. Usually we calculate the digit sum using a number's decimal (base 10) representation, but in this exercise we will compute it in a given base. Write a function that computes a natural number's digit sum when the number is written in a given base. Using this function, write a program that reads two natural numbers (each on its own line, and both in decimal representation): a base B and a number N. The output should be N's digit sum in base B (written in decimal representation).“
I have tried to fix the problem by adding 2 conditions, but it did nothing, mistake still exists.
I am using a formula, which can be found here https://en.wikipedia.org/wiki/Digit_sum .
Here is the code itself, it is not long.
program CifernySoucetZobecneny;
var
Soustava, Cislo, i: longint;
HorniMez: longint;
Soucet: real;
function Mocnina(Zaklad: longint; Exponent: longint): longint;
var
i, Pomoc: longint;
begin
Pomoc := 1;
for i := 1 to Exponent do
begin
Pomoc := Pomoc * Zaklad;
end;
Mocnina := Pomoc;
end;
begin
readLn(Soustava);
readLn(Cislo);
if (Soustava = 0) then
begin
writeLn('0');
exit;
end;
if (Soustava = 1) then
begin
writeLn(Cislo);
exit;
end;
HorniMez := Trunc(Ln(Cislo)/Ln(Soustava));
Soucet := 0;
for i := 0 to HorniMez do
begin
Soucet := Soucet + ((1/Mocnina(Soustava, (i)))*((Cislo mod Mocnina(Soustava, (i+1))) - (Cislo mod Mocnina(Soustava, i))));
end;
writeLn(Soucet:0:0);
end.
I would be grateful if someone could look at the code and told me, where am I dividing by 0, because I tried many inputs, spend many hours on this and did not come with the correct solution. Thank you all.
PS: I am Czech, so the names of the variables and functions are not in English, sorry for that, but I hope, that it will not be a problem.
When Cislo = 0, a following calculation of Ln(Cislo) gives the runtime error 200. That is because Ln(0) is undefined (outside the allowed range of Ln()).

ada invalid index constraint

I defined a matrix type in ada like this:
type Matrix_Type is array(Natural range <>, Natural range <>) of Item_Type;
in order to apply some transformations to an input matrix, I need to define a matrix slice in a function.
I tried that by doing it the following way
procedure Do_Stuff(M: Matrix_Type) is
-- c needs to be half as big as the input matrix M
C: Matrix_Type(A'Length / 2, A'Length / 2);
begin
...
end Do_Stuff;
However, compiling fails with the error: invalid index constraint which I don't quite understand, since Putting A'Length returns a number as A'Length /2 does. If I declare C using fixed numbers like that
C: Matrix_Type(2,2);
everything works fine.
What is the error in that case, the only possible case in which I would understand it kind of would be if I pass some uninitialized Matrix to the function, and even that doesn't quite make sense to me.
The index constraint for the matrix C should be a range:
procedure Do_Stuff(M: Matrix_Type) is
-- C needs to be half as big as the input matrix M
C : Matrix_Type(M'First .. M'Length / 2, M'First .. M'Length / 2);
begin
…
end Do_Stuff;
For non-square matrices, you can use the Operations of Array Types to specify a particular index:
C : Matrix_Type(M'First(1) .. M'Length(1) / 2, M'First(2) .. M'Length(2) / 2);

How to set VHDL vector size based on the log of a constant

I would like to know what is corresponding VHDL code for $clog2(DATA_WIDTH) , for example in this line:
parameter DATA_OUT_WIDTH = $clog2(DATA_WIDTH)
and also for this sign " -: " in this example
if ( Pattern == In[i_count-:PATTERN_WIDTH] )
I will appreciate if anyone can help me.
You can do something like this
constant DATA_OUT_WIDTH : positive := positive(ceil(log2(real(DATA_WIDTH))));
or define a clog2 function encapsulating that expression. ceil and log2 can be found in math_real
use ieee.math_real.all;
In VHDL you can just specify the full range, for example
foo(i_count to i_count + 7)
foo(i_count downto i_count - 7)
Don't use In as an identifier though, it's a reserved word in VHDL.
In addition to Lars example you can easily write a function for finding the ceiling log 2 to determine the number of element address 'bits' necessary for some bus width. Some vendors or verification support libraries provide one already.
The reason there isn't a predefined function in an IEEE library already is expressed in Lars answer, you tend not to use it much, you can assign the value to a constant and an expression can be cobbled together from existing functions.
An example clog2 function
A borrowed and converted log2 routine from IEEE package float_generic:
function clog2 (A : NATURAL) return INTEGER is
variable Y : REAL;
variable N : INTEGER := 0;
begin
if A = 1 or A = 0 then -- trivial rejection and acceptance
return A;
end if;
Y := real(A);
while Y >= 2.0 loop
Y := Y / 2.0;
N := N + 1;
end loop;
if Y > 0.0 then
N := N + 1; -- round up to the nearest log2
end if;
return N;
end function clog2;
The argument A type NATURAL prevents passing negative integer values. Rounding is strict, any remainder below 2.0 causes rounding up.
Note that because this uses REAL and uses division it's only suitable for use during analysis and elaboration. It's a pure function.
You could note Lars example:
constant DATA_OUT_WIDTH : positive := positive(ceil(log2(real(DATA_WIDTH))));
has the same constraints on use for analysis (locally static) and elaboration (globally static). REAL types are generally not supported for synthesis and floating point operations can consume lots of real estate.
The if condition
if ( Pattern == In[i_count-:PATTERN_WIDTH] )
Is a base index (an lsb or msb depending on ascending or descending declared bit order) and a width.
See IEEE Std 1800-2012 (SystemVerilog), 11.5.1 Vector bit-select and part-select addressing.
An indexed part-select is given with the following syntax:
logic [15:0] down_vect;
logic [0:15] up_vect;
down_vect[lsb_base_expr +: width_expr]
up_vect[msb_base_expr +: width_expr]
down_vect[msb_base_expr -: width_expr]
up_vect[lsb_base_expr -: width_expr]
The msb_base_expr and lsb_base_expr shall be integer expressions, and the width_expr shall be a positive constant integer expression. Each of these expressions shall be evaluated in a self-determined context. The lsb_base_expr and msb_base_expr can vary at run time. The first two examples select bits starting at the base and ascending the bit range. The number of bits selected is equal to the width expression. The second two examples select bits starting at the base and descending the bit range.
In VHDL terms this would be a slice with bounds determined from the high index and a width by subtraction.
PATTERN_WIDTH can be globally static (as in a generic constant) as well as locally static (a non-deferred constant). i_count can be variable.
Depending on the declared range of In for example:
constant DATAWIDTH: natural := 8;
signal In_in: std_logic_vector (31 downto 0);
The equivalent expression would be
if Pattern = In_in(i_count downto i_count - DATAWIDTH - 1) then
Note that if the slice length or i_count is less than DATAWIDTH - 1 you'll get a run time error. The - 1 is because In_in'RIGHT = 0.
Without providing the declarations for In (or Pattern) and DATAWIDTH a better answer can't be provided. It really wants to be re-written as VHDL friendly.
Note as Lars indicated in is reserved word (VHDL is not case sensitive here) and the name was changed.

Comparing reals in VHDL

My current method of comparing two reals (after calculations) is to take the difference and cast to an integer and compare to 0, for example (just to highlight the problem, example might work in simulator)
variable a : real := 0.1;
constant epsilon : real := 1.0E-5; -- Whatever accuracy needed, not too low though
a := a + 5.3;
assert a = 5.4; -- Yields intermitent errors
assert integer(a - 5.4) = '0'; -- Erroneous if 4.8 < a < 5.9 due to cast rounding
assert abs(a - 5.4) < epsilon; -- Will work everytime, but seems a bit forced
The reason for this way is that I got a lot of assertion errors in an testbench I wrote (a tad more complext then the example code). I was accounting these errors as floating point errors in GHDL simulator. Is there a better way to compare two reals to each other, like using machine epsilon, or any build in methods?
As indicated by #Philippe, comparison of reals requires some margin to account for limited precision and accumulated errors in the least significant bits. Using a simple epsilon value is one common way to do this but it has a limitation in that its value is absolute in relation to the numbers being compared. You need to know in advance the expected values you're comparing to pick a suitable epsilon.
If the set of numbers you need to compare covers a wide range of magnitudes you end up with an epsilon that is too large for properly comparing small values. In this situation you'd want a small epsilon when comparing small reals and a larger epsilon for larger numbers. This is accomplished by using a comparison that accounts for relative error.
This page gives a good overview of a method that allows comparison of reals using relative error rather than absolute error. The following function is an implementation of the relative comparison in VHDL:
-- Adapted from: http://floating-point-gui.de/errors/comparison/
function relatively_equal(a, b, epsilon : real) return boolean is
begin
if a = b then -- Take care of infinities
return true;
elsif a * b = 0.0 then -- Either a or b is zero
return abs(a - b) < epsilon ** 2;
else -- Relative error
return abs(a - b) / (abs(a) + abs(b)) < epsilon;
end if;
end function;
Here the epsilon parameter is a fraction that specifies the number of significant digits to compare for relative equality.
-- Compare for relative equality to three significant digits
-- These are all considered equal while using the same epsilon parameter
assert relatively_equal(1.001, 1.002, 1.0E-3) report "1.001 != 1.002";
assert relatively_equal(100.1, 100.2, 1.0E-3) report "100.1 != 100.2";
assert relatively_equal(1001.0, 1002.0, 1.0E-3) report "1001 != 1002";
-- Compare for relative equality to four significant digits
-- This will raise the assertion
assert relatively_equal(1.001, 1.002, 1.0E-4) report "1.001 != 1.002";
This question is generic to any programming language that uses "real" values (a.k.a. floating point numbers).
The standard way to compare reals in automatic tests is to define an small value epsilon. Then check that the absolute difference between your two reals is less than epsilon. You can define your own procedure assertEqual(x,y, epsilon) if you want to write concise test benches.
procedure assertEquals(
x, y : real; epsilon : real := 1.0E-5;
message : string := "";
level : severity_level := error) is
begin
assert (abs (x - y) < epsilon) report message severity level;
end procedure assertEquals;

ISO pascal and recursivity

I can not find out what is the correct behaviour of this program according to ISO pascal standard. I tried to read the ISO 7185 Standard document but did not find anything on this topic. What should be the result 4 or 24 ?
program Undetermined;
var
n: Integer;
function fact: Integer;
begin
fact := 1;
if n > 1 then
begin
n := n - 1;
fact := (n + 1) * fact
end
end;
begin
n := 4;
writeln( fact )
end.
EDIT : I realised that there is a second problem in my example. So consider the new code :
program Undefined;
var
n: Integer;
function power2: Integer;
begin
power2 := 1;
if n > 0 then
begin
n := n - 1;
power2 := 2 * power2
end
end;
begin
n := 4;
writeln( power2 )
end.
The result should be 16 or 2 (according to my compiler) ?
EDIT : thanks for the answer event if they did not solve my problem. I finally got the right answer on an other forum : the ISO-standard specify the behaviour I expected but the compiler I use (fpc) does not conform the standard on that point with the default settings.
There are two separate issues here:
Does fact denote the result of the function, or a recursive call?
If it does denote a recursive call, is the result 24 or implementation defined?
1. Does fact denote the result of the function, or a recursive call?
Since fact doesn't occur on the left side of an assignment, it doesn't correspond to the result of the function, so it should invoke the function recursively. The compiler treating fact and fact() differently in this context sounds like a bug.
The standard says:
Within an activation, an applied occurrence of a label or variable-identifier, or of a procedure-identifier or function-identifier local to the block of the activation, shall denote the corresponding program-point, variable, procedure, or function, respectively, of that activation; except that the function-identifier of an assignment-statement shall, within an activation of the function denoted by that function-identifier, denote the result of that activation.
2. If it does denote a recursive call, is the result 24 or implementation defined?
Even if you disregard the recursion related issue, and use fact(), you still can't expect to always get 24 as a result.
It boils down to: "Is (n+1) or fact() evaluated first in the expression (n + 1) * fact?
The order of evaluation is implementation defined in this case. This means that different implementations following the standard can give different results, and you can't expect 24 for all of them.
To quote the standard:
6.7.2 Operators
6.7.2.1 General
Table 3 | Dyadic arithmetic operations
...
* Multiplication
...
A factor, a term, or a simple-expression shall be designated an operand. The order of evaluation of the operands of a dyadic operator shall be implementation-dependent.
NOTE | This means, for example, that the operands may be evaluated in textual order, or in reverse order, or in parallel, or they may not both be evaluated.
Free Pascal's ISO dialect mode is very young (1-2 years), as FPC generally is a Borland and not ISO oriented compiler.
The Mac Pascal mode is more tested, and is in general very ISO like. Compiling in macpascal mode will yield the "16" answer without ().
Probably ISO mode should do the same and not use the borland/delphi like return value is a pseudo variable. Please file a bug.

Resources