* * *

Author Topic: Strange error while trying my program.  (Read 3885 times)

Bart

  • Hero Member
  • *****
  • Posts: 3114
    • Bart en Mariska's Webstek
Re: Strange error while trying my program.
« Reply #15 on: February 11, 2018, 05:57:32 pm »
No, system.sqrt is only necessary for the internal calculation of the overloaded sqrt in another place. E.g. the real part.

Sorry, I misunderstood you.

Anyhow, the error described (main.pp(55,10) Error: Illegal expression) was PEBKAC.
I tried to use extended syntax on sqrt(integervalue) which apparently is not allowed. Sqrt(integer) is an internproc, and it seems interproc's don't support extended syntax.

Bart

Thaddy

  • Hero Member
  • *****
  • Posts: 6895
Re: Strange error while trying my program.
« Reply #16 on: February 11, 2018, 06:07:39 pm »
Quick and compiles, no tests:
My idea is based on this link:
https://stackoverflow.com/questions/15074316/request-simple-example-of-how-to-a-tcomplexmath-class-source-included
Code: Pascal  [Select]
  1.  
  2. {$mode delphi}
  3. uses math;
  4. type
  5.   TComplex = record
  6.     r:double;
  7.     i:double;
  8.   end;
  9.  
  10. function Sqrt(const c:TComplex): TComplex;
  11. var
  12.   x, y, v, w: Double;
  13. begin
  14.   if (c.i =0) and (c.r=0) then begin
  15.     Result.r:=0;
  16.     Result.I:=0;
  17.   end else begin
  18.     x := abs(c.r);
  19.     y := abs(c.i);
  20.     if x>=y then begin
  21.       v := y/x;
  22.       w := System.Sqrt(x)*System.Sqrt(0.5*(1.0+System.Sqrt(1.0+v*v)));
  23.     end else begin
  24.       v := x/y;
  25.       w := System.Sqrt(y)*System.Sqrt(0.5*(v+System.Sqrt(1.0+v*v)));
  26.     end;
  27.     if c.r>=0.0 then begin
  28.       Result.r := w;
  29.       Result.i := c.i/(2.0*w);
  30.     end else begin
  31.       if c.i>=0.0 then begin
  32.         Result.i := w;
  33.       end else begin
  34.         Result.i := -w;
  35.       end;
  36.       Result.r := c.i/(2.0*Result.i);
  37.     end;
  38.   end;
  39. end;
  40. begin
  41. end.
  42.  
Not sure about the first line of code...
« Last Edit: February 11, 2018, 06:09:32 pm by Thaddy »
Ada's daddy wrote this:"Fools are my theme, let satire be my song."

Bart

  • Hero Member
  • *****
  • Posts: 3114
    • Bart en Mariska's Webstek
Re: Strange error while trying my program.
« Reply #17 on: February 11, 2018, 06:32:13 pm »
Hmm, the implementation of csqrt() looks rather different...

Bart

Thaddy

  • Hero Member
  • *****
  • Posts: 6895
Re: Strange error while trying my program.
« Reply #18 on: February 11, 2018, 06:36:16 pm »
 O:-) Yes, Hmmm...
Ada's daddy wrote this:"Fools are my theme, let satire be my song."

Bart

  • Hero Member
  • *****
  • Posts: 3114
    • Bart en Mariska's Webstek

Thaddy

  • Hero Member
  • *****
  • Posts: 6895
Re: Strange error while trying my program.
« Reply #20 on: February 11, 2018, 07:14:46 pm »
Bart, even if this code proves incorrect it demonstrates a way of getting around your issue, doesn't it?
Ada's daddy wrote this:"Fools are my theme, let satire be my song."

wp

  • Hero Member
  • *****
  • Posts: 4970
Re: Strange error while trying my program.
« Reply #21 on: February 11, 2018, 08:05:01 pm »
The general solution of solving a quadratic equaltion with *REAL* coefficients does not require the function csqrt. The sqrt of a negative number x is sqrt(-x)*i (i = imaginary number). The well-known formula then can be applied. But since the square-root term is a complex number the routines in unit ucomplex are needed for the remaining calculations (complex addition, subtractiion and, most of all, division).

Code: Pascal  [Select]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   SysUtils, ucomplex;
  7.  
  8. function ComplexToStr(z: complex; Decimals: Integer): String;
  9. var
  10.   sr, si: String;
  11. begin
  12.   sr := Format('%.*f', [Decimals, z.re]);
  13.   si := Format('%.*fi', [Decimals, z.im]);
  14.   if z.im < 0 then Result := sr + si else Result := sr + '+' + si;
  15. end;
  16.  
  17. var
  18.   a, b, c: Double;
  19.   z1, z2: complex;
  20.   b2_4ac: Double;
  21. begin
  22.   a := 2;
  23.   b := 1;
  24.   c := 3;
  25.   b2_4ac := b*b - 4*a*c;
  26.  
  27.   WriteLn('Solve a*z^2 + b*z + c = 0');
  28.   WriteLn(' with a = ', a:0:3);
  29.   WriteLn('      b = ', b:0:3);
  30.   WriteLn('      c = ', c:0:3);
  31.   WriteLn;
  32.   WriteLn('b^2 - 4ac = ', b2_4ac:0:3);
  33.   WriteLn;
  34.   if b2_4ac < 0 then begin
  35.     z1 := cinit(-b, sqrt(-b2_4ac));
  36.     z2 := cinit(-b, -sqrt(-b2_4ac));
  37.   end else begin
  38.     z1 := cinit(-b, sqrt(b2_4ac));
  39.     z2 := cinit(-b, -sqrt(b2_4ac));
  40.   end;
  41.   z1 := z1 / (2*a);
  42.   z2 := z2 / (2*a);
  43.  
  44.   WriteLn('1st solution z1 = ', ComplexToStr(z1, 3));
  45.   z1 := cinit(a, 0)*csqr(z1) + cinit(b, 0)*z1 + cinit(c, 0);
  46.   WriteLn('Test: a*z1^2 + b*z1 + c = ', ComplexToStr(z1, 6));
  47.   WriteLn;
  48.   WriteLn('2nd solution z2 = ', ComplexToStr(z2, 3));
  49.   z2 := cinit(a, 0)*csqr(z2) + cinit(b, 0)*z2 + cinit(c, 0);
  50.   WriteLn('Test: a*z2^2 + b*z2 + c = ', ComplexToStr(z2, 6));
  51.   ReadLn;
  52. end.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

Kays

  • Full Member
  • ***
  • Posts: 112
  • Whasup!?
    • KaiBurghardt.de
Re: Strange error while trying my program.
« Reply #22 on: February 11, 2018, 09:22:41 pm »
[…] a simple program to solve Quadratic equations […]
Code: Pascal  [Select]
  1. []
  2. Raiz:=sqrt((b*b)-4*(a*c));
  3. []

Uhm, when you first heard about the quadratic formula, you probably heard about “el determinante” and its properties, too, didn't you? So, why don't you use it?

Just to mention three tricks:
  • you can declare multiple variables of the same type by separating identifiers with commas
  • an array[boolean] of string[1] for the sign
  • readLn can read multiple arguments (you don't have to call readLn three times separately)
Code: Pascal  [Select]
  1. program quadraticFormula(input, output, stderr);
  2.  
  3. uses
  4.         // sysutils for format function
  5.         sysutils,
  6.         // gettext for internationalization
  7.         gettext;
  8.  
  9. // resourcestrings {{{
  10. resourcestring
  11.         prompt = 'Enter the integers a, b, c as in ax²+bx+c:';
  12.         equationResult = 'The equation %0:dx²%1:s%2:dx%3:s%4:d';
  13.         oneRealRootOnly = ' has the root x₀ ⩰ %0:.3f.';
  14.         twoRealRoots = ' has roots at x₀ ⩰ %0:.3f and x₁ ⩰ %1:.3f.';
  15.         complexRootsOnly = ' has no real roots.';
  16. // }}}
  17.  
  18. var
  19.         a, b, c: integer;
  20.         determinant, vertex_x, root_offset: extended;
  21.         sign: array[boolean] of string[1];
  22.  
  23. begin
  24.         translateResourceStrings('./' + applicationName() + '.%s.mo');
  25.        
  26.         writeLn(prompt);
  27.         readLn(a, b, c);
  28.        
  29.         determinant := sqr(b) - 4 * a * c;
  30.        
  31.         // '-' (minus) is generated by format function
  32.         sign[false] := '';
  33.         sign[true] := '+';
  34.        
  35.         write(format(equationResult, [a, sign[b >= 0], b, sign[c >= 0], c]));
  36.        
  37.         if determinant >= 0 then
  38.         begin
  39.                 vertex_x := -1 * (b / (2 * a));
  40.                
  41.                 if determinant > 0 then
  42.                 begin
  43.                         root_offset := sqrt(determinant / (4 * sqr(a)));
  44.                        
  45.                         writeLn(format(twoRealRoots,
  46.                                 [vertex_x - root_offset, vertex_x + root_offset]));
  47.                 end
  48.                 else
  49.                 begin
  50.                         writeLn(format(oneRealRootOnly, [vertex_x]));
  51.                 end;
  52.         end
  53.         else
  54.         begin
  55.                 writeLn(complexRootsOnly);
  56.         end;
  57. end.
Have fun learning Pascal, Rubén.
« Last Edit: February 11, 2018, 09:27:50 pm by Kays »
Yours Sincerely
Kai Burghardt

engkin

  • Hero Member
  • *****
  • Posts: 2109
Re: Strange error while trying my program.
« Reply #23 on: February 11, 2018, 11:47:54 pm »
[snipped]
Code: Pascal  [Select]
  1.   if b2_4ac < 0 then begin
  2.     z1 := cinit(-b, sqrt(-b2_4ac));
  3.     z2 := cinit(-b, -sqrt(-b2_4ac));
  4.   end else begin
  5.     z1 := cinit(-b, sqrt(b2_4ac));
  6.     z2 := cinit(-b, -sqrt(b2_4ac));
  7.   end;

I think you meant to write:
Code: Pascal  [Select]
  1.   if b2_4ac < 0 then begin
  2.     z1 := cinit(-b, sqrt(-b2_4ac));
  3.     z2 := cinit(-b, -sqrt(-b2_4ac));
  4.   end else begin
  5.     z1 := cinit(-b+sqrt(b2_4ac), 0);
  6.     z2 := cinit(-b-sqrt(b2_4ac), 0);
  7.   end;

Otherwise we get wrong answers for b2_4ac > 0.

Edit:
I am not sure why you avoided using csqrt:
Code: Pascal  [Select]
  1. var
  2.   sqrt_delta: complex;
  3. ...
  4.   sqrt_delta := csqrt(sqr(b)-4*(a*c));
  5.   z1 := (-b + sqrt_delta) / (2*a);
  6.   z2 := (-b - sqrt_delta) / (2*a);
« Last Edit: February 12, 2018, 12:06:37 am by engkin »

wp

  • Hero Member
  • *****
  • Posts: 4970
Re: Strange error while trying my program.
« Reply #24 on: February 12, 2018, 01:20:28 am »
I think you meant to write:
Code: Pascal  [Select]
  1.   if b2_4ac < 0 then begin
  2.     z1 := cinit(-b, sqrt(-b2_4ac));
  3.     z2 := cinit(-b, -sqrt(-b2_4ac));
  4.   end else begin
  5.     z1 := cinit(-b+sqrt(b2_4ac), 0);
  6.     z2 := cinit(-b-sqrt(b2_4ac), 0);
  7.   end;

Otherwise we get wrong answers for b2_4ac > 0.
Right - the devil of copy and paste, and I did not test this case.

I am not sure why you avoided using csqrt
Ah, of course...
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus