### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: case of  (Read 9287 times)

#### flori

• Full Member
• Posts: 183
##### case of
« on: March 04, 2021, 01:22:13 pm »
Hi everyone!
I have a small demo which categorize the contents of the leaf (such as apple, apricot leaf, etc)  ... low, medium high

Code: Pascal  [Select][+][-]
1. Case Round(StringToNumber(edit6.Text)*100) of
2.    2000..3000: N_res.text:='low';
3.      End;
4. case Round(StringToNumber(edit6.Text)*100) of
5.    3001..4000: N_res.text:='medium';
6.  End;
7. if Nlab>40.01 then N_res.text:='high';

The categories (low, medium, high) unfortunately changes many times (every day:(). I put some Edit on the form where we can give  (we can specify) the values  (low: 20-30, medium: n1-n2, high<n)
Does anyone know how can I change code
Code: Pascal  [Select][+][-]
1. 2000..3000: N_res.text:='low'
to calculate based on what I type (what values) into edit? (categorize based on what I type edits)
I attached demo
Thank you

#### Roland57

• Full Member
• Posts: 153
##### Re: case of
« Reply #1 on: March 04, 2021, 01:31:10 pm »
Hello! I don't believe it be possible to use "case of" that way.

Maybe you could use the InRange function from the Math unit.

Regards.

Roland

#### MarkMLl

• Hero Member
• Posts: 2423
##### Re: case of
« Reply #2 on: March 04, 2021, 02:13:23 pm »
I agree: the values have to be constant at compilation time.

OP: you've got extra ends in your example: should be something like

Code: Pascal  [Select][+][-]
1.     Case Round(StringToNumber(edit6.Text)*100) of
2.        2000..3000: N_res.text:='low';
3.        3001..4000: N_res.text:='medium'
4.     otherwise
5.        if Nlab>40.01 then
6.          N_res.text:='high'
7.        else
8.          N_res.text:='GOK'
9.      End;
10.

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

#### flori

• Full Member
• Posts: 183
##### Re: case of
« Reply #3 on: March 04, 2021, 02:53:07 pm »
yes. But I would like to change: (see the picture)

#### Zvoni

• Hero Member
• Posts: 529
##### Re: case of
« Reply #4 on: March 04, 2021, 02:56:01 pm »
Not possible with Case Of
As Roland said: Use InRange from math
One System to rule them all, One IDE to find them,
One Code to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
People call me crazy, because i'm jumping out of perfectly fine aircraft

#### flori

• Full Member
• Posts: 183
##### Re: case of
« Reply #5 on: March 04, 2021, 02:56:32 pm »
ok I will try

#### Zvoni

• Hero Member
• Posts: 529
##### Re: case of
« Reply #6 on: March 04, 2021, 03:04:57 pm »
quick and dirty (and not tested)
Code: Pascal  [Select][+][-]
1. Var
2.   iMin:Integer;
3.   iMax:Integer;
4. .
5. .
6. .
7. iMin:=StringToNumber(editLeft.Text)*100;
8. iMax:=StringToNumber(editRight.Text)*100;
9.
10. If InRange(StringToNumber(edit6.Text)*100, iMin, iMAx) Then Do SomeThing;
11.
One System to rule them all, One IDE to find them,
One Code to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
People call me crazy, because i'm jumping out of perfectly fine aircraft

#### flori

• Full Member
• Posts: 183
##### Re: case of
« Reply #7 on: March 04, 2021, 03:41:19 pm »
I modified :unfortunately it's not good either

Code: Pascal  [Select][+][-]
1. function InRange ..
2. var
3.   iMin:real;
4.   iMax:real;
5. begin
6. iMin:=StringToNumber(Edit1.Text);
7. iMax:=StringToNumber(Edit2.Text);
8.
9. If InRange (Round((StringToNumber(edit6.Text)*100)), iMin, iMAx) then
10.    N_res.Text:='low' else N_res.Text:='error dose';

end;

#### Kays

• Sr. Member
• Posts: 299
• Whasup!?
##### Re: case of
« Reply #8 on: March 04, 2021, 03:50:55 pm »
I agree: the values have to be constant at compilation time.
Background information: The rationale is that the compiler must be able to verify that all case label values are disjunct, there is no overlap.

[…] Does anyone know how can I change code
Code: Pascal  [Select][+][-]
1. 2000..3000: N_res.text:='low'
to calculate based on what I type (what values) into edit? (categorize based on what I type edits)[…]
You must “translate”, i.e. displace and scale your values to ranges you know at compile-time, something like:
Code: Pascal  [Select][+][-]
1. uses
2.         // for `sign`, but this is not /really/ necessary
3.         math;
4.
5. type
6.         category = (low, medium, high);
7.         categoryLimits = record
8.                         // values including and above this threshold are `medium`
9.                         lowMediumThreshold: integer;
10.                         // values including and above this threshold are `high`
11.                         mediumHighThreshold: integer;
12.                 end;
13.
14. function categorization(
15.                 value: integer;
16.                 const definition: categoryLimits
17.         ): category;
18. begin
19.         with definition do
20.         begin
21.                 assert(lowMediumThreshold < mediumHighThreshold);
22.
23.                 // normalize
24.                 value := value - lowMediumThreshold;
25.                 value := floor(value / (mediumHighThreshold - lowMediumThreshold));
26.                 value := sign(value);
27.         end;
28.
29.         case value of
30.                 -1:
31.                 begin
32.                         categorization := low;
33.                 end;
34.                 0:
35.                 begin
36.                         categorization := medium;
37.                 end;
38.                 1:
39.                 begin
40.                         categorization := high;
41.                 end;
42.                 otherwise
43.                 begin
44.                         assert(false);
45.                 end;
46.         end;
47. end;
Then you can still use the case language construct.
Yours Sincerely
Kai Burghardt

#### flori

• Full Member
• Posts: 183
##### Re: case of
« Reply #9 on: March 04, 2021, 03:58:29 pm »
Kays: thanks the background info

#### flori

• Full Member
• Posts: 183
##### Re: case of
« Reply #10 on: March 04, 2021, 05:00:38 pm »
unfortunately it does not work really with InRange (sure i don't use it well)?

#### glorfin

• Full Member
• Posts: 128
• LMath supporter
##### Re: case of
« Reply #11 on: March 04, 2021, 05:54:58 pm »
unfortunately it does not work really with InRange (sure i don't use it well)?
Yes, use of InRange implies use of if then else construct instead of case.
So, you have basically two choices: if then else instead of case, or map your values like Kay suggested. Personally I would use If Then Else with InRange.

#### GetMem

• Hero Member
• Posts: 4001
##### Re: case of
« Reply #12 on: March 04, 2021, 05:57:58 pm »
@flori

You implemented your on version of InRange function which body is empty, remove it, then add math to the uses.  Instead of TEdit use TFloatSpinEdit, you can directly enter float values and set the Min/Max. Much easier this way.

#### flori

• Full Member
• Posts: 183
##### Re: case of
« Reply #13 on: March 04, 2021, 06:09:41 pm »
Yes.
unfortunately for some reason it is miscategorized  (low dose)
is my code wrong?

Code: Pascal  [Select][+][-]
1. var
2. iMin:Double;
3. iMax:Double;
4.
5. iMin:=StringToNumber(Edit1.Text);
6. iMax:=StringToNumber(Edit2.Text);
7.
8. If InRange (Round((StringToNumber(edit6.Text)*100)), iMin, iMAx) then
9.    N_res.Text:='low' else N_res.Text:='error dose';
« Last Edit: March 04, 2021, 06:11:12 pm by flori »

#### WooBean

• Full Member
• Posts: 112
##### Re: case of
« Reply #14 on: March 06, 2021, 11:36:02 am »
Just remark to "case" documentation - we can use ranges not limited to 0..255.

Below some code which I find a self explaining:
Code: Pascal  [Select][+][-]
1. program project1;
2. var i:integer;
3.
4. begin
5.   i:=1024;
6.
7. {\$R-} //needed to force compiling line below
8.   writeln('Result of "',i,' in [1000..1025]" is ',i in [1000..1025]);
9. //project1.lpr(9,63) Warning: range check error while evaluating constants (1025 must be between 0 and 255)
10. //project1.lpr(9,57) Warning: range check error while evaluating constants (1000 must be between 0 and 255)
11. {\$R+} //now range checking is turned on
12.   write('In case selector range value ',i);
13.   case i of
14.   1000..1025: writeln(' is between 1000..1025');
15.   else
16.     writeln(' is not between 1000..1025'); // never to happen
17.   end;
18.
19.   i:=1026;
20.   write('In case selector range value ',i);
21.   case i of
22.   1000..1025: writeln(' is between 1000..1025');
23.   else
24.     writeln(' is not between 1000..1025'); // never to happen
25.   end;
26.
27.
28.   write('In case selector ranges value ',i);
29.   case i of
30.   1000..1025,1030..1032: writeln(' is among ranges 1000..1025,1030..1032');
31.   else
32.     writeln(' is not among ranges 1000..1025,1030..1032');
33.   end;
34.
35.   write('In case selector ranges value ',i);
36.   case i of
37.   1000..1005,1025..1032: writeln(' is among ranges 1000..1005,1025..1032');
38.   else
39.     writeln(' is not among ranges 1000..1005,1025..1032');
40.   end;
41.