Recent

Author Topic: This is WIERD  (Read 956 times)

J-G

  • Hero Member
  • *****
  • Posts: 1023
This is WIERD
« on: May 28, 2026, 11:33:19 am »
I've just come across a peculiar result from a maths equation which makes absolutely no sense (to me).

Background is a program I'm writting to solve triangles. Most things are working as expected but since there are potentially an infinite number of potential 'Triangles' and I'm allowing only 3 of the 6 values to be specified, I've found that some data is 'special' inasmuch as it needs alternative code.

The particular issue is that a formula when used as a single line returns zero but when evaluated as separate functions returns the correct value.

Knowing two sides (B & C) and the enclosed angle (alpha), the length of the unknown side (A)  is given by  :

A := Sqrt( B2 + C2 - (2*B*C * Cos(alpha)))

In the case that B=3, C=6 and Alpha = 60°  -  Laz returns ZERO from this formula but if I code :
Code: Pascal  [Select][+][-]
  1.       begin
  2.         A := b*b + c*c;
  3.         A := A - (2*b*c * cos_a);
  4.         A := Sqrt(A);
  5.       end
  6.  
'A' is returned correctly!

I cannot fathom this so I'd appreciate any thoughts as to what I'm doing wrong (with the one-line code) ?

« Last Edit: May 28, 2026, 12:40:05 pm by J-G »
FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

vangli

  • Jr. Member
  • **
  • Posts: 57
Re: This is WIERD
« Reply #1 on: May 28, 2026, 11:56:48 am »
Hi, you do input 60 degree as radians? Like PI/3 aprox 1.047. Trig functions in Pascal use radians.

Edited: Deleted a wrong statement
« Last Edit: May 28, 2026, 12:08:40 pm by vangli »
Regards Bent

dseligo

  • Hero Member
  • *****
  • Posts: 1686
Re: This is WIERD
« Reply #2 on: May 28, 2026, 12:00:23 pm »
This code:
Code: Pascal  [Select][+][-]
  1. program project1;
  2. const b = 3;
  3.       c = 6;
  4.       alpha = 60;
  5. var a: Double;
  6. begin
  7.   A := b*b + c*c;
  8.   A := A - (2*b*c * cos(alpha));
  9.   A := Sqrt(A);
  10.   WriteLn(a:10:2);
  11.  
  12.   A := Sqrt( B*b + C*c - (2*B*C * Cos(alpha)));
  13.   WriteLn(a:10:2);
  14.  
  15.   ReadLn;
  16. end.

...gives this:
Code: Text  [Select][+][-]
  1.       8.90
  2.       8.90

wp

  • Hero Member
  • *****
  • Posts: 13550
Re: This is WIERD
« Reply #3 on: May 28, 2026, 12:00:53 pm »
Look carefully at your code, you must be doing something wrong.

The two calculations yield the same result, for sure:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. uses
  3.   Math;
  4. var
  5.   b: Double = 3.0;
  6.   c: Double = 6.0;
  7.   alpha: Double = 60.0;
  8.   cos_alpha: Double;
  9.   a: Double;
  10. begin
  11.   cos_alpha := cos(DegToRad(alpha));
  12.   a := sqrt(b*b + c*c - 2*b*c*cos_alpha);
  13.   WriteLn(a:0:3);
  14.  
  15.   a := b*b + c*c;
  16.   a := a - 2*b*c*cos_alpha;
  17.   a := sqrt(a);
  18.   WriteLn(a:0:3);
  19.  
  20.   ReadLn;
  21. end.
  22.  
  23. // Output:
  24. 5.196
  25. 5.196

J-G

  • Hero Member
  • *****
  • Posts: 1023
Re: This is WIERD
« Reply #4 on: May 28, 2026, 12:19:37 pm »
Hi, you do input 60 degree as radians? Like PI/3 aprox 1.047. Trig functions in Pascal use radians.

Good call @vangli  :)  but I made that mistake many moons ago -  I now have a 'Rads' Routine that is called for all Trig functions.

Since this particular piece of code doesn't actually call the SinCos function that wouldn't have been relevant as it happens  -  but it's always good to raise a potential issue.
FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

J-G

  • Hero Member
  • *****
  • Posts: 1023
Re: This is WIERD
« Reply #5 on: May 28, 2026, 12:38:38 pm »
Look carefully at your code, you must be doing something wrong.

The two calculations yield the same result, for sure:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. uses
  3.   Math;
  4. var
  5.   b: Double = 3.0;
  6.   c: Double = 6.0;
  7.   alpha: Double = 60.0;
  8.   cos_alpha: Double;
  9.   a: Double;
  10. begin
  11.   cos_alpha := cos(DegToRad(alpha));
  12.   a := sqrt(b*b + c*c - 2*b*c*cos_alpha);
  13.   WriteLn(a:0:3);
  14.  
  15.   a := b*b + c*c;
  16.   a := a - 2*b*c*cos_alpha;
  17.   a := sqrt(a);
  18.   WriteLn(a:0:3);
  19.  
  20.   ReadLn;
  21. end.
  22.  
  23. // Output:
  24. 5.196
  25. 5.196

At least you came up with the correct answer @WP  -  I cannot see how @Dseligo gets 8.9 ??

I've re-checked everything and added a line :-
Code: Pascal  [Select][+][-]
  1.       begin
  2.         A := b*b + c*c;
  3.         A := A - (2*b*c * cos_a);
  4.         A := Sqrt(A);
  5.         D := Sqrt((b*b + c*c) - ((2*b*c) * cos_a))
  6.       end
  7.  

I've even added extra brackets which shouldn't make any difference in this case.

'A' comes back as 5.19615 ...    but D = 0  ????

The ONLY difference I can see between our two codes is that I've declared A,B,C,D & Alpha  as Single rather than Double. No angle is ever goiing to exceed 360 (more likely < 180)  and the sides aren't going to be anywhere near the 3.4E38 limit :)

I cannot see that 'Single' or 'Double' would make any difference though.

FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

dseligo

  • Hero Member
  • *****
  • Posts: 1686
Re: This is WIERD
« Reply #6 on: May 28, 2026, 12:46:49 pm »
I cannot see how @Dseligo gets 8.9 ??

It's because I didn't convert degrees to radians. But it still shows that problem was with your code and not Free Pascal.

bytebites

  • Hero Member
  • *****
  • Posts: 787
Re: This is WIERD
« Reply #7 on: May 28, 2026, 12:49:23 pm »
Code: Pascal  [Select][+][-]
  1.       begin
  2.         A := b*b + c*c;
  3.         A := A - (2*b*c * cos_a);
  4.         A := Sqrt(A);
  5.         D := Sqrt((b*b + c*c) - ((2*b*c) * cos_a))
  6.       end

Is this Python or Java, not variable definitions.

wp

  • Hero Member
  • *****
  • Posts: 13550
Re: This is WIERD
« Reply #8 on: May 28, 2026, 12:58:37 pm »
What is your "cos_a"? When alpha is 60 (in degrees) the correct expression is: cos_a := cos(DegToRad(alpha)) - DegToRad converts degrees to radians and is in unit Math (there is also an inverse one, RadToDeg, for radians to degrees).

Single vs. double should not make a difference.

J-G

  • Hero Member
  • *****
  • Posts: 1023
Re: This is WIERD
« Reply #9 on: May 28, 2026, 01:13:24 pm »
Is this Python or Java, not variable definitions.

?? we're in a 'Lazarus' forum so it's Pascal ??
FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

MathMan

  • Hero Member
  • *****
  • Posts: 515
Re: This is WIERD
« Reply #10 on: May 28, 2026, 01:24:09 pm »
@J-G

I only see two options to get ahead with this

1 - can you provide a compilable version that replicates your issue?
2 - if not, can you at least start the debugger and provide the assembler output that the compiler produced for your code snippet?

Khrys

  • Sr. Member
  • ****
  • Posts: 456
Re: This is WIERD
« Reply #11 on: May 28, 2026, 01:24:41 pm »
Is this Python or Java, not variable definitions.

?? we're in a 'Lazarus' forum so it's Pascal ??

That means "where and how are your variables defined?"

J-G

  • Hero Member
  • *****
  • Posts: 1023
Re: This is WIERD
« Reply #12 on: May 28, 2026, 01:51:38 pm »
What is your "cos_a"? When alpha is 60 (in degrees) the correct expression is: cos_a := cos(DegToRad(alpha)) - DegToRad converts degrees to radians and is in unit Math (there is also an inverse one, RadToDeg, for radians to degrees).

Single vs. double should not make a difference.

As I've said before, (answer to @vangli) I got over the 'Convert to Radians'  pot-hole a long time ago.  I now have a procedure which I call whenever any angle is declared or changed :-
Code: Pascal  [Select][+][-]
  1. procedure SCT(Ang : Single;N : char);      // Calc Sin - Cos - Tan
  2. begin
  3.   SinCos(Rads(Ang),Sin_X,Cos_X);
  4.   Tan_X := Tan(Rads(Ang));
  5.   case N of
  6.     'A' : begin
  7.             Sin_a := Sin_X;
  8.             Cos_a := Cos_X;
  9.             Tan_a := Tan_X;
  10.           end;
  11. [...]
  12.   end;
  13.  

and a Function :-  (or rather 2 . . . )
Code: Pascal  [Select][+][-]
  1. Function  Rads(x : real) : real;
  2. begin
  3.   rads := x * 0.0174532925199433;
  4. end;
  5. Function  Degs(x : real) : real;
  6. begin
  7.   degs := x / 0.0174532925199433;
  8. end;
  9.  

In this case I do know that Cos_a is correctly returned as 0.5.

I know that I need all (well most of) the functions of any Angle as well as those of half the Angle so the full proc. does both. so it seems more efficient to make a single call such as - - - - SCT(Alpha,'A') and know that I have then set Sin_a, Cos_a, Tan_a, Sin_½a, Cos_½a, Tan_½a  and can use any with impunity.
That is rather than calling the separate functions as and when the need arrises.


FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

Khrys

  • Sr. Member
  • ****
  • Posts: 456
Re: This is WIERD
« Reply #13 on: May 28, 2026, 02:18:49 pm »
so it seems more efficient to make a single call such as - - - - SCT(Alpha,'A') and know that I have then set Sin_a, Cos_a, Tan_a, Sin_½a, Cos_½a, Tan_½a  and can use any with impunity.

Missed an opportunity to optimize  Tan_X  as  Sin_X / Cos_X  :P
But seriously, where are your variable definitions? What are their types? Which units does your program use? All these questions could be avoided by posting a compilable example  ;)

J-G

  • Hero Member
  • *****
  • Posts: 1023
Re: This is WIERD
« Reply #14 on: May 28, 2026, 02:20:26 pm »
@J-G

I only see two options to get ahead with this

1 - can you provide a compilable version that replicates your issue?
2 - if not, can you at least start the debugger and provide the assembler output that the compiler produced for your code snippet?
Thanks for your interest @MathMan.

My code could probably considered quite 'rambling' and I am in the process of tidying it up!  It amounts to 5600+ lines with the offending code at 4480-4490.

Your second option may well be more efficient but regrettably beyond my ability :) so I've put a copy of five files on my web-site  - Triangle.Res  - .Lps - .Lpr - .Lpi  & .ico  so you can download whatever you need to look further.

I've left the D:= . . . .  in place although it is never used elsewhere, it's just there for viweing via the 'Debug' facility.  I've also commented out the Uses JGDT, my own date/time unit which I haven't as yet implimented and I don't beleive I've used any third party units - so all should be straight-forward but do let me know if you have any problems.

On first [run] it will ask where you want to store data -  this is just a couple of variables that can be modified by the user (Decimal places & size of display text) so that they can be restored to whatever the user last set.


FPC 3.0.0 - Lazarus 1.6 &
FPC 3.2.2  - Lazarus 2.2.0 
Win 7 Ult 64

 

TinyPortal © 2005-2018