Recent

Author Topic: what's wrong with my code ? :D  (Read 5505 times)

mikex

  • New member
  • *
  • Posts: 7
what's wrong with my code ? :D
« on: November 29, 2014, 06:44:09 pm »
I have written code in pascal ...
program pr2;
//division of number into integer and fractional parts
procedure StrToChs(s:string; var tr,fr:string);
var p:byte;
begin
p:=pos('.',s);
if p=0
then
 begin
  tr:=s;
  fr:='';
 end
else if p=length(s) then
 begin
  tr:=copy(s,1,p-1);
  fr:='';
 end
else if p=1 then
 begin
  tr:='';
  fr:=copy(s,2,length(s)-1);
 end
else
 begin
  tr:=copy(s,1,p-1);
  fr:=copy(s,p+1,length(s)-p);
 end;
end;
//bringing the integer parts of numbers to one length
procedure NormT(var s1,s2:string; var n:byte);
var n1,n2:byte;
begin
n1:=length(s1);
n2:=length(s2);
if n1>n2 then
 begin
  n:=n1;
  while length(s2)<length(s1) do s2:='0'+s2;
 end
else if n2>n1 then
 begin
  n:=n2;
  while length(s1)<length(s2) do s1:='0'+s1;
 end;
end;
//bringing the fractional parts of numbers to one length
procedure NormF(var s1,s2:string; var n:byte);
var n1,n2:byte;
begin
n1:=length(s1);
n2:=length(s2);
if n1>n2 then
 begin
  n:=n1;
  while length(s2)<length(s1) do s2:=s2+'0';
 end
else if n2>n1 then
 begin
  n:=n2;
  while length(s1)<length(s2) do s1:=s1+'0';
 end;
end;
//addition of the fractional parts
function SumFrac(s1,s2:string; n:byte; var p:byte):string;
var s3:string;
    i:byte;
    a1,a2,a3:array[byte] of byte;
begin
for i:=1 to n do
 begin
  a1:=ord(s1)-48;
  a2:=ord(s2)-48;
 end;
p:=0;
for i:=n downto 1 do
  begin
   a3:=a1+a2+p;
   if (a3>9)and(i>1) then
      begin
       a3:=a3 mod 10;
       p:=1;
      end
    else p:=0;
  end;
if a3[1]>9 then //transmit into the main program the first digit of the integer part of number (0 or 1)
 begin
  a3[1]:=a3[1] mod 10;
  p:=1;
 end
else p:=0;
s3:='';
for i:=1 to n do
s3:=s3+chr(a3+48);
SumFrac:=s3;
end;
//addition of the integer parts
function SumTrunc(s1,s2:string; n,p:byte):string;
var s3:string;
    i:byte;
    a1,a2,a3:array[byte] of byte;
begin
for i:=1 to n do
 begin
  a1:=ord(s1)-48;
  a2:=ord(s2)-48;
 end;
for i:=n downto 1 do
  begin
   a3:=a1+a2+p;
   if (a3>9)and(i>1) then
      begin
       a3:=a3 mod 10;
       p:=1;
      end
    else p:=0;
  end;
if a3[1]>9 then
  begin
    a3[1]:=a3[1] mod 10;
    n:=n+1;
    for i:=n downto 2 do
    a3:=a3[i-1];
    a3[1]:=1;
  end;
s3:='';
for i:=1 to n do
s3:=s3+chr(a3+48);
SumTrunc:=s3;
end;
 
var s1,s2,s1t,s1f,s2t,s2f,s3t,s3f:string;
    nt,nf,p:byte;
begin

writeln('Enter two decimal number (no more than 100 characters), decimal separator is dot');
readln(s1);
readln(s2);
StrToChs(s1,s1t,s1f);
StrToChs(s2,s2t,s2f);
NormT(s1t,s2t,nt);
NormF(s1f,s2f,nf);
if (s1f='')and(s2f='') then s3f:=''
else
 begin
  s3f:=SumFrac(s1f,s2f,nf,p);
  s3f:='.'+s3f;
 end;
if (s1t='')and(s2t='') then s3t:='0'
else s3t:=SumTrunc(s1t,s2t,nt,p);
write(s3t,s3f);

end.


 But i cant find the mistake  .. it counts numbers wrong but why ? :)))))))

Number 777.777 + 333 result is .777 and thats wrong.

Code is made on this example 

They are given two "long" positive decimal numbers , each of which can have up to 100 digits and can contain a decimal point . If does not contain a decimal point , it is understood that this is an integer (as if the decimal point was located at the end) . Write a program that reads the number specified in the input and computes their sum and displays it .

Example 1:
To enter in the form:
77777777777777777777
333
program prints the result :
77777777777777778110

Example 2:
To enter in the form:
777777777777777.77
3.33333
program prints the result :
777777777777781.10333

Any ideas whete did i made mistake ?

Bart

  • Hero Member
  • *****
  • Posts: 5290
    • Bart en Mariska's Webstek
Re: what's wrong with my code ? :D
« Reply #1 on: November 29, 2014, 07:27:14 pm »
Sounds like a school assignment.

First of all: put your code inside code-tags (the button with the # will do it for you).
Somewhere you have an "i" inside "[]", which the forum software translates into: from here-on use italics....
Also it handles indentation better.

I would do it like this:
  • Make sure both strings have equal amount of digits after the decimalseparator (pad with zeros if necessary).
  • Make sure both strings are of equal length (left-pad the shorter one with zero's)
  • Add the two strings proceding from right to left like you learned at school: 5 + 6 = 1, carry 1 to the left.
  • Ignore the decimalseparator (just skip)
  • Remove any trailing 0
  • If the result starts with a decimalseparator then insert a 0 at the beginning
  • If the results ends in a decimalseparator then remove that
  • Done

The adding part:
  • n := length(number1)
  • carry := false
  • result := ''  //empty string
  • repeat
  •   if number1[n] = decimalseparator then insert decimalseparator and continue  //look up the meaning of continue in a loop!
  •   v1 := integer value of number1[v] //use either val() or StrToInt() or a clever trick with Ord()
  •   v2 := integer value of number2[v]
  •   v3 := v1 + v2
  •   if carry then v3 := v3  + 1
  •   set carry to true if v3 > 9, otherwise set it to false
  •   if carry then v3 := v3 - 10 //v1 + v2 can never be > 19, no need to use mod()
  •   result := character value of v3 + result //use str() or IntToStr()
  •   decrement n
  • until n= 0
  • if carry then result := '1' + result

Bart
« Last Edit: November 29, 2014, 07:33:39 pm by Bart »

mikex

  • New member
  • *
  • Posts: 7
Re: what's wrong with my code ? :D
« Reply #2 on: November 29, 2014, 07:48:24 pm »
Yes you're right it's school assignment

Interesting ideas
I'm on it thanks for advice and your help.


howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: what's wrong with my code ? :D
« Reply #3 on: November 29, 2014, 08:17:42 pm »
It's your SumFrac and SumTrunc procedures that are wrong. They don't even compile for me.
This might give you some more ideas:

Code: [Select]
function SumFrac(const s1, s2: string; out addOne: boolean): string;
var
  a, i, len, carry, res: integer;
begin
  len:=Length(s1);
  if (Length(s2) <> len) then
   Exit;

  SetLength(Result, len);
  carry:=0;

  for i:=len downto 1 do
  begin
    a:=Ord(s1[i]) + Ord(s2[i]) - 96 + carry;
    res:=a mod 10;
    carry:=a div 10;
    Inc(res, 48);
    Result[i]:=chr(res);
  end;

  addOne:=(carry <> 0);
end;

Bart

  • Hero Member
  • *****
  • Posts: 5290
    • Bart en Mariska's Webstek
Re: what's wrong with my code ? :D
« Reply #4 on: November 30, 2014, 02:22:05 pm »
Since this is a school assignement probably you have to use "classic" syntax:
  • No const parameters for functions/procedures
  • No "Result" in functions
  • No Sysutils, Classes etc
  • No StringOfChar
  • No AnsiStrings
  • More restrictions probably

Who can write the fastest, yet still readable, code using this restrictions (and not using inline assembler!), and make the code so, that it will please the teacher? (define appropriate types and constants, separate the code into usefull procedures and functions, sanitize input etc).

Bart

BrunoK

  • Sr. Member
  • ****
  • Posts: 452
  • Retired programmer
Re: what's wrong with my code ? :D
« Reply #5 on: November 30, 2014, 04:20:03 pm »
Apart the fact I would write something a bit like howardpc.

If I'm not mistaken, in NormT and NormF you forget to give a value to var n: byte when both strings are of the same length.

The compiler gives an indication
project1.lpr(119,21) Hint: Variable "nt" does not seem to be initialized
project1.lpr(120,21) Hint: Variable "nf" does not seem to be initialized
for the  lines
  NormT(s1t, s2t, nt);
  NormF(s1f, s2f, nf);

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: what's wrong with my code ? :D
« Reply #6 on: November 30, 2014, 07:50:10 pm »
Since this is a school assignement probably you have to use "classic" syntax:
  • No const parameters for functions/procedures
  • No "Result" in functions
  • No Sysutils, Classes etc
  • No StringOfChar
  • No AnsiStrings
  • More restrictions probably

Who can write the fastest, yet still readable, code using this restrictions?

They are quite severe restrictions indeed. Here is code I hope is readable. I make no claims for it being fast.
Code: [Select]
program AdderFor100DigitNumbers;

procedure GetVerifiedNormalisedNumbers(var norm1, norm2, entry1, entry2: shortstring);
var
  s1, s2: shortstring;
  p1, p2, f1, f2, i1, i2: integer;
  verified: boolean;

  function Verify(var aNumStr: shortstring; var decimalPos: integer): boolean;
  var
    i, len: integer;
    decimal: boolean;
  begin
    Verify:=False;
    decimal:=False;
    decimalPos:=0;
    len:=Ord(aNumStr[0]);
    if (len = 0) then
      Exit;
    for i:=1 to len do
      case aNumStr[i] of
        '0'..'9': ;
        '.': if decimal then
               Exit
             else
               begin
                 decimal:=True;
                 decimalPos:=i;
               end;
        else Exit;
      end;
    if (decimalPos = 0) then
      begin
        Inc(len);
        aNumStr[0]:=Chr(len);
        aNumStr[len]:='.';
        decimalPos:=len;
      end;

    Verify:=(len <= 101);
  end;

  Procedure PadZeros(var aStr: shortstring; zeroCount: integer; addAtEnd: boolean);
  var
    pad: shortstring;
  begin
    FillChar(pad[1], zeroCount, '0');
    pad[0]:=Chr(zeroCount);
    if addAtEnd then
      aStr:=aStr + pad
    else aStr:=pad + aStr;
  end;

begin
  repeat
    Write('Enter the first of two numbers to add: ');
    ReadLn(s1);
    verified:=Verify(s1, p1);
  until verified;
  entry1:=s1;
  f1:=Succ(Ord(s1[0]) - p1);
  i1:=Pred(p1);

  repeat
    Write('Enter second number: ');
    ReadLn(s2);
    verified:=Verify(s2, p2);
  until verified;
  entry2:=s2;
  f2:=Succ(Ord(s2[0]) - p2);
  i2:=Pred(p2);

  if (f1 > f2) then
    PadZeros(s2, f1-f2, True)
  else if (f2 > f1) then
    PadZeros(s1, f2-f1, True);

  if(i1 > i2) then
    PadZeros(s2, i1-i2, False)
  else if (i2 > i1) then
    PadZeros(s1, i2-i1, False);

  norm1:=s1;
  norm2:=s2;
end;

function AddNumberStrings(s1, s2: shortstring): shortstring;
const
  One = '1';
var
  sum, j, carry, len: integer;
  addOne: boolean;
begin
  len:=Ord(s1[0]);
  if (Ord(s2[0]) <> len) then
    begin
      AddNumberStrings:='Error';
      Exit;
    end;

  carry:=0;
  AddNumberStrings[0]:=Chr(len);
  for j:= len downto 1 do
    begin
      if (s1[j] <> '.') then
        begin
          sum:=Ord(s1[j]) + Ord(s2[j]) - 96 + carry;
          carry:=sum div 10;
          AddNumberStrings[j]:=Chr((sum mod 10) + 48);
        end
      else AddNumberStrings[j]:='.';
    end;
  addOne:=(carry = 1);
  if addOne then
    AddNumberStrings:=One + AddNumberStrings;
end;

var
  e1, e2, n1, n2, n3: shortstring;

begin
  GetVerifiedNormalisedNumbers(n1, n2, e1, e2);
  n3:=AddNumberStrings(n1, n2);
  WriteLn('Adding ',e1,' to ',e2);
  WriteLn('gives the sum: ',n3);
  Write('Press [Enter] to exit ');
  Readln;
end.


Bart

  • Hero Member
  • *****
  • Posts: 5290
    • Bart en Mariska's Webstek
Re: what's wrong with my code ? :D
« Reply #7 on: November 30, 2014, 10:51:44 pm »
I would guess that with ShortStrings Length(S) will be "translated" by the compiler to S[0], so I would use Length() to make it better readable.

Let's wait with more code until topicstarter completed his school-assignment  O:-)

Bart

mikex

  • New member
  • *
  • Posts: 7
Re: what's wrong with my code ? :D
« Reply #8 on: December 01, 2014, 02:30:09 am »
Hah thanks i was trying to fix it your way then i saw post about var n: byte ... then i found i had to input the value so i fixed that with single line ;)) got 10/10 for it so im happy ;) thanks to everyone ...

Bart

  • Hero Member
  • *****
  • Posts: 5290
    • Bart en Mariska's Webstek
Re: what's wrong with my code ? :D
« Reply #9 on: December 01, 2014, 06:42:05 pm »
My solution in attachment (strcalc.lpr).

Bart

 

TinyPortal © 2005-2018