Recent

Author Topic: Error in conditionals - Lazarus 1.8.0 Win32  (Read 10443 times)

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: Error in conditionals - Lazarus 1.8.0 Win32
« Reply #15 on: February 18, 2018, 03:19:01 pm »
I copied and tested your code using step over (F8), the flow exit the multiple ifs after:

Code: Pascal  [Select][+][-]
  1.  xTmp := Char(xNum + 55);

Which means it's working correctly on my test.

I ever have experience, my code didn't work as what it should be but I fixed it by deleting the binary and lib folder and recompile again the source code. Maybe it can fix your issue too.

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: Error in conditionals - Lazarus 1.8.0 Win32
« Reply #16 on: February 18, 2018, 03:52:21 pm »
I do see your problem. It has to do with using variants in the char() function.

To illustrate:
Code: Pascal  [Select][+][-]
  1. var
  2.   xTmp ,xNum: variant;
  3. begin
  4.   xNum := 27;
  5.   xTmp := char(xNum + 55);
  6.   Showmessage(xTmp + ' is different from ' + char(27 + 55));
  7. end;
This will show "8 is different from R".

The problem is char(xNum + 55) with xNum being variant 27.

If you change it to this it will work fine:
Code: Pascal  [Select][+][-]
  1. xTmp := char(Integer(xNum) + 55);
(You'll need to do that with the other lines too. Mixing variants with numbers seems dangerous. It would be better to just convert xNum it to integer and use that.)

I'll leave it to the experts to explain why xNum is not seen as Integer when doing XNum+55 inside the Char() function (and to see if that's not a bug).

ASerge

  • Hero Member
  • *****
  • Posts: 2222
Re: Error in conditionals - Lazarus 1.8.0 Win32
« Reply #17 on: February 18, 2018, 04:37:49 pm »
Code: Pascal  [Select][+][-]
  1. //...
  2. If (IsRange(nBase, 2, 252) <> False) Then Begin
  3. If (lSwStr <> True) Then Begin
  4.  If (IsRange(xNum, 0, 9) <> False) Then xTmp := Char(xNum + 48) Else
  5. //...
  6.  
For me, it's easier:
Code: Pascal  [Select][+][-]
  1. //...
  2.   if InRange(nBase, 2, 252) then begin
  3.   if not lSwStr then begin
  4.   if InRange(xNum, 0, 9) then xTmp := Char(xNum + 48) else
  5. //...
  6.  
And stop Visual Basic style. Read Coding Guidelines for Lazarus.
My example of your code, if I understand it correctly:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. {$APPTYPE CONSOLE}
  3. {$mode objfpc}
  4.  
  5. uses Math, SysUtils;
  6.  
  7. {$WARN 3177 OFF: Some fields coming after "$1" were not initialized}
  8. const
  9.   CMagicTable: array [1..12] of record
  10.     UpTo: Integer;
  11.     case Add: Integer of
  12.       0: (Direct: Integer);
  13.   end = ( // ordered by UpTo - it is important
  14.    (UpTo:9; Add:48),
  15.    (UpTo:35; Add:55),
  16.    (UpTo:61; Add:61),
  17.    (UpTo:62; Add:0; Direct: 43),
  18.    (UpTo:63; Add:0; Direct: 47),
  19.    (UpTo:196; Add:59),
  20.    (UpTo:202; Add:-106),
  21.    (UpTo:209; Add:-145),
  22.    (UpTo:210; Add:0; Direct: 44),
  23.    (UpTo:220; Add:-178),
  24.    (UpTo:238; Add:-207),
  25.    (UpTo:251; Add:-238));
  26.  
  27. function BaseXTable(xNum: Integer; nBase: Integer): string; overload;
  28. var
  29.   Code: Integer;
  30.   Index: Integer;
  31. begin
  32.   if InRange(nBase, 2, 252) then
  33.   begin
  34.     Code := xNum;
  35.     for Index := Low(CMagicTable) to High(CMagicTable) do
  36.     begin
  37.       if Code <= CMagicTable[Index].UpTo then
  38.       begin
  39.         if CMagicTable[Index].Add <> 0 then
  40.           Inc(Code, CMagicTable[Index].Add)
  41.         else
  42.           Code := CMagicTable[Index].Direct;
  43.         Exit(Chr(Code));
  44.       end;
  45.     end;
  46.   end;
  47.   Result := '*** Error ***';
  48. end;
  49.  
  50. function BaseXTable(const xNum: string; nBase: Integer): string; overload;
  51. var
  52.   S: string;
  53.   Code: Integer;
  54.   Min, Max, Index: Integer;
  55.   Fit: Boolean;
  56. begin
  57.   if InRange(nBase, 2, 252) then
  58.   begin
  59.     S := Trim(xNum);
  60.     if nBase < 36 then
  61.       Code := Ord(UpCase(S[1]))
  62.     else
  63.       Code := Ord(S[1]);
  64.     for Index := Low(CMagicTable) to High(CMagicTable) do
  65.     begin
  66.       if CMagicTable[Index].Add = 0 then
  67.       begin
  68.         if Code = CMagicTable[Index].Direct then
  69.         begin
  70.           Code := CMagicTable[Index].UpTo;
  71.           Break;
  72.         end;
  73.       end
  74.       else
  75.       begin
  76.         Min := CMagicTable[Index].Add;
  77.         Max := CMagicTable[Index].Add + CMagicTable[Index].UpTo;
  78.         if Min <= Max then
  79.           Fit := InRange(Code, Min, Max)
  80.         else
  81.           Fit := InRange(Code, Max, Min);
  82.         if Fit then
  83.         begin
  84.           Dec(Code, CMagicTable[Index].Add);
  85.           Break;
  86.         end;
  87.       end;
  88.     end;
  89.     if Code < nBase then
  90.       Exit(Chr(Code));
  91.   end;
  92.   Result := '*** Error ***';
  93. end;
  94.  
  95. begin
  96.   Writeln(BaseXTable(27, 36));
  97.   Writeln(BaseXTable(BaseXTable(27, 36), 36));
  98.   Readln;
  99. end.


Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Error in conditionals - Lazarus 1.8.0 Win32
« Reply #18 on: February 18, 2018, 05:03:43 pm »
OK, totally off-topic, but this really hurts my eyes.

Code: Pascal  [Select][+][-]
  1. Function BaseXTable(xNum: Variant; nBase: Extended; lSwStr: Boolean): Variant;  
  2. ...
  3. Begin
  4. ...
  5. If (IsRange(nBase, 2, 252) <> False) Then Begin
  6. If (lSwStr <> True) Then Begin
  7. ...
  8. End;
  9.  

OMG!
I don't even know where to begin here.

IsRange() returns a boolean, why compare it to another boolean, and why "<>False"?
The "<>False" suggests that there are more options than True/False.
Essentially "<>False" is "not False", which of course is "True".

So you want to know if IsRange() returns True.
The proper way to do so is simply:
Code: Pascal  [Select][+][-]
  1. If IsRange(nBase, 2, 252) Then Begin

And mutatis mutandis (google that):
Code: Pascal  [Select][+][-]
  1. If  not lSwStr Then Begin

[rant]
And no, comparing a Boolean to True or False does NOT make your code better readable.
Also if you do that, you are rather inconsistent, since the expression (ABoolean = False) results in yet another boolean expression, and you seem to have decided that you need to compare a Boolean expression agains either True of False, so to be consistent you should do if ((ABoolean=False)=True), but even this then is a Boolean expression, which, by your standards has to be compared against True or False, so it needs to be extended to (((ABoolean=False)=True)=True), which unfortunately in itself is a Boolean expression, which in all fairness needs to be compared against True or False, so we get ((((ABoolean=False)=True)=True)=True), which of course still is not enough, so
Code: Pascal  [Select][+][-]
  1. (((((ABoolean=False)=True)=True)=True)=True)
etc. etc.
And to be absolutely sure that the compiler knows about True and False, you need to start each Boolean expression by
Code: Pascal  [Select][+][-]
  1.   if not (True xor False) then FatalError;
Just because, you know, the compiler may be off a bit, or you run fpc on a quantum computer, where a Boolean can be True and False at the same time, or even not True and not False (google Schrödingers cat), and this will screw up the logic of your program, so if you run the program on such a system you must abort it (and preferrably display a message stating that programs compiled with freepascal cannot run on quantum computers, and that the compiler sucks and that this has nothing to do with possible bugs in your code, because, you know, you have decades of experience in designing compilers that run flawlessly, because you are a genius, and you really know the meaning of Boolean expressions and why you always must compare them against absolute True and/or False and ....
[/rant]

Sorry, I got a little bit carried away.

The main point of course is that I sincerely wish you have fun programming, wether this is in Pascal or some other language.
And that you don't mind that some grumpy old man, that sometimes wishes programming was as simple as in the days of Turbo Pascal 3.0, writes grumpy comments in threads you started.

If you feel up to it, please rewrite your Boolean expressions to be a litle more in line with the language you write them in.

Bart
« Last Edit: February 18, 2018, 05:06:09 pm by Bart »

WooBean

  • Full Member
  • ***
  • Posts: 229
Re: Error in conditionals - Lazarus 1.8.0 Win32
« Reply #19 on: February 18, 2018, 08:49:06 pm »
@rvk
Quote
I do see your problem. It has to do with using variants in the char() function.

imho char is a type and char() is a typecasting (some purists write Char rather).
What do you expect doing typecasting char(variant_variable)?

Code below works as spirit of Pascal (language) comanded.

Code: Pascal  [Select][+][-]
  1.   var
  2.     xTmp ,xNum: variant;
  3.   begin
  4.     xNum := 27;
  5.     xTmp := chr(xNum + 55); //chr() but not char()!!!
  6.     //Showmessage(xTmp + ' is different from ' + char(27 + 55)); //
  7.     writeln(xTmp + ' is NOT different from ' + chr(27 + 55));
  8.     readln;
  9.   end.
  10.  
Output of this console application is: R is NOT different from R


Anyway, I find once more that "simple" or "stupid" question can teach us a lot.
« Last Edit: February 18, 2018, 08:51:29 pm by WooBean »
Platforms: Win7/64, Linux Mint Ulyssa/64

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: Error in conditionals - Lazarus 1.8.0 Win32
« Reply #20 on: February 18, 2018, 09:02:06 pm »
Quote
I do see your problem. It has to do with using variants in the char() function.
imho char is a type and char() is a typecasting (some purists write Char rather).
Ah, yes, you are correct. Char() is a type and not a function. Chr() would be better.

Although Integer() is also a type and this works correctly:
Code: Pascal  [Select][+][-]
  1. Showmessage(integer(xNum + 55).tostring + ' is the same as ' + integer(27 + 55).tostring);
But that's probably because some typecasts do convert correctly (like string() cast etc).

I do see now where the result is coming from:
Code: Pascal  [Select][+][-]
  1. var
  2.   xTmp ,xNum: variant;
  3. begin
  4.   xNum := 27;
  5.   xNum := xNum + 55;
  6.   xTmp := char(xNum); // <-- xNum is 82 here so char(xNum) will be 8
  7.   Showmessage(xTmp { 8 } + ' is different from ' + char(27 + 55) { R });

So xNum + 55 is 82. Because this is a variant it is both integer 82 and string 82. But when casting string 82 to a char you'll get the 8 (which is the result of the function).

I do understand why topicstarter got in trouble here (although I wouldn't have used variants at all for this).
« Last Edit: February 18, 2018, 09:04:05 pm by rvk »

Thaddy

  • Hero Member
  • *****
  • Posts: 14202
  • Probably until I exterminate Putin.
Re: Error in conditionals - Lazarus 1.8.0 Win32
« Reply #21 on: February 19, 2018, 08:05:39 am »
And to be absolutely sure that the compiler knows about True and False, you need to start each Boolean expression by
Code: Pascal  [Select][+][-]
  1.   if not (True xor False) then FatalError;

Bart
Well Bart, you can't be absolutely sure anymore because true and false are not keywords (anymore).
Code: Pascal  [Select][+][-]
  1.   const true = false;
  2.   if not (True xor False) then FatalError;
<Grumpy >:D> >
Try:
Code: Pascal  [Select][+][-]
  1. const
  2.  maybe = true;true = false;false=maybe;
  3. begin
  4.   writeln(maybe,true,false);
  5. end.
« Last Edit: February 19, 2018, 08:14:59 am by Thaddy »
Specialize a type, not a var.

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Error in conditionals - Lazarus 1.8.0 Win32
« Reply #22 on: February 19, 2018, 08:46:43 pm »
Better yet, use my boolfactory unit, which takes into account quantum fluctuations regarding true and or false.

Bart

sam707

  • Guest
Re: Error in conditionals - Lazarus 1.8.0 Win32
« Reply #23 on: February 20, 2018, 02:08:48 am »
@PsaCrypt
ever think about boolean evaluation way in fpk compiler?

https://www.freepascal.org/docs-html/prog/progsu4.html

sometimes it is better to enclose boolean evaluations with
{$B+} or [$BOOLEVAL ON}
as told on the above link, to ensure that the compiler will do a complete test and not a shortCUT

Thaddy

  • Hero Member
  • *****
  • Posts: 14202
  • Probably until I exterminate Putin.
Re: Error in conditionals - Lazarus 1.8.0 Win32
« Reply #24 on: February 20, 2018, 07:39:00 am »
Better yet, use my boolfactory unit, which takes into account quantum fluctuations regarding true and or false.

Bart
Neat, but it does not cover a fundamental: it looks like true and false particles in quantum state are in synced state. The reason that true and false appear to differ in value is that when the state of either is examined both state changes.
In quantum terms true and false are actually equal, so when you read true, true becomes false and false becomes false. Now when you read false, true becomes true again, but false too. Not many programmers realize that  :o O:-) :-X
Confused? you won't be after the next episode of https://www.youtube.com/watch?v=QTpm0k23iV4 Demonstrates both synced and true.... O:-)
« Last Edit: February 20, 2018, 11:44:52 am by Thaddy »
Specialize a type, not a var.

Thaddy

  • Hero Member
  • *****
  • Posts: 14202
  • Probably until I exterminate Putin.
Re: Error in conditionals - Lazarus 1.8.0 Win32
« Reply #25 on: February 20, 2018, 07:52:15 am »
@PsaCrypt
ever think about boolean evaluation way in fpk compiler?

https://www.freepascal.org/docs-html/prog/progsu4.html

sometimes it is better to enclose boolean evaluations with
{$B+} or [$BOOLEVAL ON}
as told on the above link, to ensure that the compiler will do a complete test and not a shortCUT
Serious note:
There is another very important reason to have boolean evaluation ON and that is the calculation of cryptographic algorithms : even though results between ON/OFF should be the same, with {$B-} the algorithm becomes vulnerable to timing attacks. https://en.wikipedia.org/wiki/Timing_attack
I even wrote a patch (issues 29287-29290) for some FPC hashes for that and those patches were accepted for that reason. Only in {$B+} state the calculation has always equal time.
If you see a cryptographic algorithm that depends on boolean logic implemented in  {$B-} state that should be considered a bug for that reason.

A second important reason is profiling: you can only do serious profiling when at least some tests are done in {$B+} state, otherwise you do not know what you are measuring. Again,  Only in {$B+} state the calculation has always equal time. You can then subsequently test in {$B-} and reverse evaluation order if necessary until you find the optimal shortcut evaluation. "Most likely" should come first --> left. "Least likely" should come last in the evaluation order. Given "equal weight", the least computational expensive should usually come first. (Assuming logical AND operations, of course)
This can have a dramatic impact on the speed of your code.
« Last Edit: February 20, 2018, 11:53:57 am by Thaddy »
Specialize a type, not a var.

sam707

  • Guest
Re: Error in conditionals - Lazarus 1.8.0 Win32
« Reply #26 on: February 20, 2018, 05:28:28 pm »
I was indicating the {$BOOLEVAL} switch to @PsaCrypt, in a simple explanation because I think it is what he is looking for on the starter Post.

I'm naturally mixing B+ and B- when I go crypto, for years  ;) thanks, but that wasn't what I understood from the question with its easy code snippet

About the rest of the late conversation, I will wait Quantum Pascal Compiler to try the "more or less" "between states" "mixing multiple states" human attitude on ex-binary machines becomming more conscious
 :P
I think it's offtopic for now, and we lost 47 987 newbies on that last (just kidding)
« Last Edit: February 20, 2018, 05:34:16 pm by sam707 »

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Error in conditionals - Lazarus 1.8.0 Win32
« Reply #27 on: February 20, 2018, 05:45:19 pm »
Better yet, use my boolfactory unit, which takes into account quantum fluctuations regarding true and or false.

Bart
Neat, but it does not cover a fundamental: it looks like true and false particles in quantum state are in synced state. The reason that true and false appear to differ in value is that when the state of either is examined both state changes.

Patches are welcome!

Bart

Thaddy

  • Hero Member
  • *****
  • Posts: 14202
  • Probably until I exterminate Putin.
Re: Error in conditionals - Lazarus 1.8.0 Win32
« Reply #28 on: February 21, 2018, 12:16:15 pm »
Therefor I added a more serious note...
Specialize a type, not a var.

Josh

  • Hero Member
  • *****
  • Posts: 1271
Re: Error in conditionals - Lazarus 1.8.0 Win32
« Reply #29 on: February 21, 2018, 12:49:21 pm »
@Thaddy
Quote
Today I became $111100

Happy 60th Birthday  ;)
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

 

TinyPortal © 2005-2018