Division by 0 in TurboPascal7 - pascal

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()).

Related

I'm having some problems with even and odd numbers in Pascal

I'm having some problems with my program in Pascal. I need to create a program which will calculate even and odd sums of a number's decomposition. For example, if my number is 10 the program should write that sum of even numbers is 30 (since 2,4,6,8,10 are the even numbers) and it should write that sum of odd numbers is 25 (since 1,3,5,7,9 are odd numbers). Here is what i tried
program odd_even;
var
a,sumeven,sumodd,even,odd : integer;
begin
writeln('Enter a number : ');
readln(a);
if a mod 2 = 0 then a=even;
if a mod 2 not=0 then a=odd;
for a:1 to a do begin
sumeven:=0;
sumeven:=sumeven+even
writeln('Sum of even numbers is : ',sumeven);
sumodd:=0;
sumodd:=sumodd+odd;
writeln('Sum of odd numbers is : ',sumodd),
end;
readln
end.
The compiler says that my if part is illegal but I don't understand how I can fix it, I also tried with else but it says the same thing. If someone could help me out I would be really thankful.
First of all, welcome to the world of programming!
There are several errors in your code:
The initialization of your result variables
sumEven:=0;
sumOdd:=0;
should be before your for loop
checking odd/even
if a mod 2 = 0 then a=even;
if a mod 2 not=0 then a=odd;
should be inside your loop and you should check not whether a (your input number) is odd/even but the value of your loop variable:
for i := 1 to a do
begin
if (i mod 2 <> 0) then sumOdd := sumOdd+1 else sumEven := sumEven+1 ;
end;
Printing the results should be of course after your loop.
Good luck!

how to write reciprocal value of a number in pascal?

I'm having some problems with a program in pascal.
I need to enter a number and than I need the program to write an addition of reciprocal value of that number. It sholud be something like this : let's say the number is 5 (n=5) then I need my program to write 1/1 + 1/2 + 1/3 + 1/4 + 1/5 and a result of this addition , I need to use for,to,do in order to get a solution, so if someone could help me, I'd be really thankful.
I tried something like this :
program reciprocaladdition;
var x : integer:
begin
writeln('enter number');
readln(x);
for x:=1 to x do writeln(1/x:0:2)
readln
end.
but it doesnt give me whaat i need so if someone could help me id be thankful.
Your has a couple of typos:
the colon after integer should be a semicolon; and
the writeln needs a semicolon after it because there is another statement (readln) after it.
Apart from that, it compiles and runs fine in Lazarus + FPC. In the corrected version below, I've added code to calculate and display the sum of the intermediate values.
program reciprocals;
var
x : integer;
Sum : Double; // a floating-point datatype
begin
writeln('enter number');
readln(x);
Sum := 0;
for x:=1 to x do begin
writeln(1/x:0:2);
Sum := Sum + 1/x;
end;
writeln('Sum: ', Sum:0:2);
readln
end.
This produces the output
enter number
3
1.00
0.50
0.33
Sum: 1.83
Does that do what you want it to? If not, please say why.

Pascal - Write all divisors of a number and sum them up

I just started programming and we were given the assignment in the title. I have no idea how to get those numbers in a summable form, so I thought that i will at least write them out, but for some reason i can't see, it doesn't work. Any advice?
var
a,i: integer;
del: array [1..32767] of boolean;
begin
i:=1;
readln(a);
for i:=1 to 32767 do del[i]:=false;
while i<>a do
begin
for i:=1 to 32767 do
begin
if (a MOD i =0) then del[i]:=true;
end
end;
if del[i] then writeln(i,' je delitelem ',a);
end.
Please consider that I am a total newb, thanks!
You're on the right path, but you don't actually even need to store the divisors - just output each one as it is found ( mod = 0 ) and add its value to an accumulator variable.
And then you also don't need the while. Instead, change your for loop to only go up to a instead of 32767.

How can I speed up a primality checker?

I have a function FIsPrime which takes a int64 and returns a boolean True or False depending on whether the given int64 is prime or not.
function FIsPrime(P:int64):boolean;
var
I:int64;
RSqrtP:Extended;
begin
I:= 3;
RSqrtP := sqrt(P) + 1;
while ((P mod I) <> 0) AND (I <= RSqrtP) AND ((P mod 2) <> 0) do
I := I + 2;
if I < RSqrtP then
FIsPrime := False
else
FIsPrime := True;
end;
However, while this works, it's quite slow. To check the numbers from 106 to 5×106 takes 4 seconds.
I'm testing numbers on the order of 1012 and 1015 - the whole code picks a random number and × it by 1012 to get a large random number.
This random number is run through the FIsPrime function and incremented by 1 untill it is prime:
function FFirstPrimeAbove(P:int64):int64;
var
BIsPrime: boolean;
begin
if P mod 2 = 0 then
inc(P);
repeat
BIsPrime := FIsPrime(P);
P := P + 2;
until (BIsPrime);
FFirstPrimeAbove := P;
end;
This can take a while - around 6 seconds for 1012 and 7 for 1015.
While 14 seconds isn't much, it is annoying. Is there a way to reduce this time with a more efficient algorithm?
I'm fairly new to Pascal, but have been programming for years - so any more efficient algorithm would be useful.
I looked at the AKS Test but there is a lot of jargon to overcome - "polynomial congruence relation", "generalization to polynomials" and "binomial coefficient" to pick a few.
Any basic hints as to how I could implement something in Delphi would be appreciated.
Changing RSqrtP to Int64 would most likely improve preformance. I didn't test it, but I'd expect comparing a float value to an int64 value not to be the fastest.
Take ((P mod 2) <> 0) out of the loop.
Also, if you don't mind having a longer initialisation time for your application, you could load a list of all prime between 2 and X and start with them before going to the I+2 routine. You don't need to try to divide by non prime number, as this is already taken care of by prime one (i.e. Anything that can be divided by 4 will be divided by 2, anything that can be divided by 49 will also be by 7, etc)
I posted an article about optimisation using primes as an example a while ago. Maybe you'll see some more information there that could help you.
I suspect that the most effective simple way to improve the speed is to create a table of known primes.
There are probably too many primes to store all that fit in a 64 bit integer. But you can store all primes less that sqrt(high(int64)). Then when you loop throw possible divisors you can check only against primes. That should provide a very significant benefit.
So, the algorithm is, in outline:
Fill an array with all the primes less than sqrt(high(int64)). This should be pre-calculated.
To test a value N for being prime, first find its root, sqrt(N).
Then try to divide primes into the value under test until you reach a prime greater than sqrt(N).
If you get that far, N is prime. Otherwise if you find a prime divisor, it is not prime.

How to insert the probability of randomizing a specific number in pascal

I've been trying lately to write a program(a text based game) but I only know some commands and don't understand every command very well.
What I am trying to do is a hit chance. Lets say that I want the program to have
90% chance of choosing number 1 (which means hit) and
10% to choose number 0 (which means miss).
I saw the same question Here but I don't understand the commands because I've never used them (I'm talking about set.seed and sample). Could someone explain to me how do they work? Is there another way (easier to understand? I don't mind if it consumes more resource)
program Project1;
{$ASSERTIONS ON}
function getProb(aProbability: Integer): boolean;
begin
result := aProbability > (100 - random(100));
end;
procedure miss;
begin
writeln('miss');
end;
procedure hit;
begin
writeln('hit');
end;
var
i, success, probability, errorMarge: Integer;
const
combat: array[boolean] of procedure = (#miss, #hit);
begin
// show that getProb() is reliable
errorMarge := 4;
success := 0;
probability := 80;
for i in [0..99] do
Inc(success, Byte(getProb(probability)));
assert(success >= probability - errorMarge);
success := 0;
probability := 50;
for i in [0..99] do
Inc(success, Byte(getProb(probability)));
assert(success >= probability - errorMarge);
// example usage
combat[getProb(20)];
combat[getProb(80)];
combat[getProb(90)];
readln;
end.
Not knowing what "commands" you know, this is hard to answer w/o generalizing.
If you only need to choose between two values, then generate a random value in whatever range you know how to, and compute the dividing line based on your probability. So, for your example, if you can generate a value between 0 and 1, if it is <= 0.9, hit.
This can be extended to multiple values by adding the successive probabilities. So if you have 4 values to choose between, each with 25% probability, get you random value between 0 and 1: if it is less than 0.25, choose 0 else if less than 0.5, choose 1 else if less than 0.75 choose 2 otherwise choose 3.

Resources