Recent

Author Topic: Using IF...THEN or CASE?  (Read 1463 times)

chuckles1066

  • New Member
  • *
  • Posts: 20
Using IF...THEN or CASE?
« on: November 26, 2020, 04:05:59 pm »
Hi,

Just looking for the most efficient way of doing this.
Code: [Select]
library GenuineDice;
uses MMSystem;
{$mode objfpc}{$H+}

var
  RandomizeAlreadyCalled: Boolean = False;

function Dice: Integer; {$ifdef windows}stdcall{$else}cdecl{$endif};
var
  D1, D2: Integer;
begin
  // call randomize once and never again.
  if not RandomizeAlreadyCalled then begin
    Randomize;
    RandomizeAlreadyCalled := True;
  end;

  D1 := Random(6) + 1;
  D2 := Random(6) + 1;

  Result := D1 * 8 + D2;
// test sound  sndPlaySound('D:\applause2.wav', snd_Async or snd_NoDefault);
end;

exports
  Dice;

begin
end.

So I have thirty-six wav files and I want to play the one that relates to the dice rolls in the above code.  So if D1 = 6 and D2 = 4, I'd play 6-4.wav.

Which way would you suggest is the best way to achieve this, multiple IF....THEN statements or use of a CASE statement?

(I ask because in other languages I've learned (VBA and SQL) CASE statements are sometimes frowned on as being inefficient).

Thank you for reading.


jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: Using IF...THEN or CASE?
« Reply #1 on: November 26, 2020, 04:30:08 pm »

 FileName := IntToStr(D1 * D2)+.'wav';

That will give you 1.wav … 36.wav
The only true wisdom is knowing you know nothing

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Using IF...THEN or CASE?
« Reply #2 on: November 26, 2020, 04:38:46 pm »
If the wave file names corespond to the numbers, as you show, I would simply build the file name from the number returned and forget about if, case, or whatever:

Code: Pascal  [Select][+][-]
  1. { call the libray }
  2. ADice := Dice;
  3. {Then either this: }
  4. D1 = ADice div 8;
  5. D2 := ADice-D1*8;
  6. AFilename := Format('%d-%d.wav', [D1, D2]);
  7. {or simply:
  8. AFilename := Format('%d-%d.wav', [ADice div 8, ADice-D1*8]);
  9. }
  10. {Now do whatever with AFilename}

(I ask because in other languages I've learned (VBA and SQL) CASE statements are sometimes frowned on as being inefficient).

That might be if the language has poor code generation (for whatever reason); in (most compilers of) Pascal, and most other languages I know about, case statements are almost always better optimized than long chains of if...then...else
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: Using IF...THEN or CASE?
« Reply #3 on: November 26, 2020, 06:04:52 pm »
I don't know much about the FPC internals, but usually in compiled languages case statements are better for the optimizer because:
1. case statements ignore the order, if statements don't. This means that the compiler can reorder the statements for optimization
2. case statements are simple ordinal matching statements, meaning they can not contain complex logic
3. case statements basically form a jumping table, on consecutive values of a small range, this can therefore be optimized as such

But after all, as you are playing sound files, efficency is none of your concern (the loading and decoding of the file from disk is so much slower than any of your code logic, meaning you probably should go for the solution that gives you the clearest, easiest to read and maintainable code. Usually, if applicable I think these are case statements.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Using IF...THEN or CASE?
« Reply #4 on: November 26, 2020, 06:22:10 pm »
I don't know much about the FPC internals, but usually in compiled languages case statements are better for the optimizer because:

Broadly agreed, but I'd suggest that if you're looking at multiple possibilities which are... not necessarily of equal probability but are of equal rank by some metric, then it's better to write them as a nice evenly-formatted case statement. If you insist on not using a case you could do something like

Code: Pascal  [Select][+][-]
  1. if condition = 0 then
  2.   do_0
  3. else
  4.   if condition = 1 then
  5.     do_1
  6.   else...
  7.  

but it rapidly gets messy. Or you could do

Code: Pascal  [Select][+][-]
  1. if condition = 0 then begin
  2.   do_0;
  3.   exit
  4. end;
  5. if condition = 1 then begin
  6.   do_1;
  7.   exit
  8. end; ...
  9.  

or

Code: Pascal  [Select][+][-]
  1. while true do begin
  2.   if condition = 0 then begin
  3.     do_0;
  4.     break
  5.   end;
  6.   if condition = 1 then begin
  7.     do_1;
  8.     break
  9.   end; ...
  10.  

both of which are frowned upon by purists who insist that  exit  and  break  are merely concealed  goto  statements.

No, if it's a flat list of alternatives like a bulleted list use a case statement, which has the additional advantage that the possibilities are mutually exclusive and you're telling the compiler to enforce that.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Using IF...THEN or CASE?
« Reply #5 on: November 26, 2020, 08:14:45 pm »
(I ask because in other languages I've learned (VBA and SQL) CASE statements are sometimes frowned on as being inefficient).
On the contrary: Case structures in compiled languages like Pascal or C/C++ are highly efficient.
In the case of FreePascal the only exception is with Case for strings which translates to a possibly very long if/then.
I never measured SQL performance for Case, though, and that may also be dependent on the engine you use.
Note that for any language it pays off to put your case loop in natural order because some compilers - not languages - do not optimize this.
« Last Edit: November 26, 2020, 08:25:00 pm by Thaddy »
Specialize a type, not a var.

dseligo

  • Hero Member
  • *****
  • Posts: 1194
Re: Using IF...THEN or CASE?
« Reply #6 on: November 26, 2020, 11:40:46 pm »

 FileName := IntToStr(D1 * D2)+.'wav';

That will give you 1.wav … 36.wav

Are you sure?
Maybe:  FileName := IntToStr((D1-1) * 6 + D2)+.'wav';

soerensen3

  • Full Member
  • ***
  • Posts: 213
Re: Using IF...THEN or CASE?
« Reply #7 on: November 26, 2020, 11:45:14 pm »
Though there have been already enough answers to solve your problem I just felt that a lookup table was missing.

You can create a const array as a lookup table and simply use your value as an index.

Code: Pascal  [Select][+][-]
  1. const
  2.   DiceFileNames: array [0..36] of String = ('a.wav', 'b.wav', [...]);
  3.  
  4. var
  5.   FN: String;
  6. begin
  7.   FN:= DiceFileNames[D1 * D2];
  8. end;
  9.  

However I think Jamie's answer in this case is even better but in other cases lookup tables can be a good alternative to case/if statements.
Lazarus 1.9 with FPC 3.0.4
Target: Manjaro Linux 64 Bit (4.9.68-1-MANJARO)

dseligo

  • Hero Member
  • *****
  • Posts: 1194
Re: Using IF...THEN or CASE?
« Reply #8 on: November 27, 2020, 01:45:07 am »
Code: Pascal  [Select][+][-]
  1.   FN:= DiceFileNames[D1 * D2];
  2.  

You also got this line wrong.
It should be (if D1 and D2 are in the range from 1 to 6 as they are in the code of original poster):
Code: Pascal  [Select][+][-]
  1.   FN:= DiceFileNames[(D1-1) * 6 + D2 -1];
  2.  

Seenkao

  • Hero Member
  • *****
  • Posts: 546
    • New ZenGL.
Re: Using IF...THEN or CASE?
« Reply #9 on: November 27, 2020, 03:02:08 am »
So I have thirty-six wav files and I want to play the one that relates to the dice rolls in the above code.  So if D1 = 6 and D2 = 4, I'd play 6-4.wav.
function Dice: Integer;
Если вам надо проиграть файл именно в формате "6-4.waw", то функция в корне не правильная.
Вам не нужно ни каких условий, достаточно вызвать функцию, которая вернёт строку: IntToSrt(D1) + '-' + IntToStr(D2) + '.waw'
И можете воспроизводить данный файл.

Google translate:
If you need to play the file in the "6-4.waw" format, then the function is fundamentally wrong.
You don't need any conditions, just call a function that will return a string: IntToSrt (D1) + '-' + IntToStr (D2) + '.waw'
And you can play this file.
Rus: Стремлюсь к созданию минимальных и достаточно быстрых приложений.

Eng: I strive to create applications that are minimal and reasonably fast.
Working on ZenGL

egsuh

  • Hero Member
  • *****
  • Posts: 1273
Re: Using IF...THEN or CASE?
« Reply #10 on: November 27, 2020, 09:52:18 am »
Choose whichever is easy for you to understand. Performance difference is really negligible, AFAIK.

 

TinyPortal © 2005-2018