1. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Oct 2011
Posts
1
Rep Power
0

#### Code not working

Hi, first post on this site so be nice.

I've written the following function which should take three variables: height, weight and gender and from these three variables calculate and return a string telling the user whether they are underweight, overweight etc.

Code is as follows:

Function bmi(w As Single, h As Single, g As String) As Double

Dim bmiCalc As Double
bmiCalc = Round(w / h ^ 2, 1)

If g = male Then
If (bmiCalc < 20) Then
bmimean = "underweight"
ElseIf (bmiCalc >= 20 And bmiCalc < 24.9) Then
bmimean = "normal weight"
ElseIf (bmiCalc >= 24.9 And bmiCalc < 30) Then
bmimean = "overweight"
Else
bmimean = "obese"
End If
ElseIf g = female Then
If (bmiCalc < 19) Then
bmimean = "underweight"
ElseIf (bmiCalc >= 19 And bmiCalc < 23.9) Then
bmimean = "normal weight"
ElseIf (bmiCalc >= 23.9 And bmiCalc < 24) Then
bmimean = "overweight"
Else
bmimean = "obese"
End If
Else
bmimean = "invalid!"
End If
bmi = bmimean
End function

The function returns #VALUE! and I've no clue why, I can't see a problem with the script.

Any help would be massively appreciated.

Thank you.
2. No Profile Picture
Grumpier old Moderator
Devshed Supreme Being (6500+ posts)

Join Date
Jun 2003
Posts
14,439
Rep Power
4539
Look into using SELECT .. CASE rather than lots of if statements.

Also please use the forum CODE tags when posting code snips.
3. Yes you should definitely use a select case but the real problem here is that bmimean is getting a string value "normal" "overweight" but the function is returning a double (which is a decimal number) the function declaration should be changed to a string. Also bmimean is undeclared and also should be declared (dim) string

You also have problems with your literals, if g = male (a variable) instead of if g = "male" (the literal) for example.
Last edited by medialint; October 19th, 2011 at 09:21 PM.
4. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Dec 2011
Posts
23
Rep Power
0
Originally Posted by hwilko123
Hi, first post on this site so be nice.

I've written the following function which should take three variables: height, weight and gender and from these three variables calculate and return a string telling the user whether they are underweight, overweight etc.

Code is as follows:

Function bmi(w As Single, h As Single, g As String) As Double

Dim bmiCalc As Double
bmiCalc = Round(w / h ^ 2, 1)

If g = male Then
If (bmiCalc < 20) Then
bmimean = "underweight"
ElseIf (bmiCalc >= 20 And bmiCalc < 24.9) Then
bmimean = "normal weight"
ElseIf (bmiCalc >= 24.9 And bmiCalc < 30) Then
bmimean = "overweight"
Else
bmimean = "obese"
End If
ElseIf g = female Then
If (bmiCalc < 19) Then
bmimean = "underweight"
ElseIf (bmiCalc >= 19 And bmiCalc < 23.9) Then
bmimean = "normal weight"
ElseIf (bmiCalc >= 23.9 And bmiCalc < 24) Then
bmimean = "overweight"
Else
bmimean = "obese"
End If
Else
bmimean = "invalid!"
End If
bmi = bmimean
End function

The function returns #VALUE! and I've no clue why, I can't see a problem with the script.

Any help would be massively appreciated.

Thank you.
as the other have suggested and identified you have 2 mistakes and the code would run fine
(1) functions cannot pass back an incorrect type hense the error message bmimean is a string change the definition of the function to suit
(2) even if you do the above the output would be wrong as the gender tests will always fail as you cannot match the string passed in against the instantiation of a variant of unknown value in-"male" must be tested against "male" of "female" so change the input to numbers and codefy the male=0 female=1 and pass numbers or change the tests

the suggestion of using switch/select statements if a very good idea as it will improve the readability of the code and ensure that you do not have a condition in the wrong place that may cause an unexpected side effect.

select has the following sintax in most languages

select case of <somevariable or boolean>
case of <some expected value>
...here you enter the action required
case of <someother expected value>
...
case else
...here you put what to do if nothing expected happens and what to do for any unimportant values are produced or just the normal thing to do ( whatever)
end select

Another thing to remember is you need only test things as much as you need and make as many assumptions as you can... so if you aint a boy you is a girl, if a suystem is closed and well defined and you have tested against everything but x then x must be true.

you coould rewite you code like th following

Function bmi(w As Single, h As Single, g As String) As string

Dim bmiCalc As Double
bmiCalc = Round(w / h ^ 2, 1)

If g = male Then
...so the else is "well hello there missy (john wayne)"
in a select like so...

select case g

case "male"
do the boy stuff
case else
do the girl stuff
end select

just like your if the actions fall through, but unlike a pile of ifs the action jumps to the end of the selet once triggered

if you tests where on individual numbers you would build the sale select structure

select case bmicalc
case <20
bmi="underweight"
case ...
bmi="...
end select

notice because the select case terminates after triggering you can set the bmi value there and then end the function

but your values are a range and while some select statements can cope not all do...

you can put
select case bmicalc
case 20,21,22,23...
<some action>

or some times
select case bmicalc
case 20 to 29
<some action>

you will need to check or suck it and see

But you can do the boolean thing

select case TRUE
case bmicalc=20
<do action>
case (bmicalc>20)and(bmicalc<29)
<do some thing else>

the case is testing for a boolean output fron the case expressions bmicalc=20 is true when its bmicalc is 20 and so on...

so the boy stuff ...
If (bmiCalc < 20) Then
bmimean = "underweight"
ElseIf (bmiCalc >= 20 And bmiCalc < 24.9) Then
bmimean = "normal weight"
ElseIf (bmiCalc >= 24.9 And bmiCalc < 30) Then
bmimean = "overweight"
Else
bmimean = "obese"
End If

becomes ...

select case true
case (bmicalc<20)
bmi="underweight"
case (bmiCalc >= 20 )And (bmiCalc < 24.9)
bmi = "normal weight"
case (bmiCalc >= 24.9 )And (bmiCalc < 30)
bmi = "overweight"
case else
bmi="Obese"
end select

if you can use values and ranges then try

select case bmicalc
case <20
bmi="underweight"
case 20 to 24.8
bmi = "normal weight"
case 24.9 to 29.9
bmi = "overweight"
case else
bmi="Obese"
end select

I think the case test values may need to be integers, if so, as your values are to 1 decimal place... you can simply multiply your results by a factor of ten and then you will have a suitable set of testable values

like
select case bmicalc*10
case <200
bmi="underweight"
case 200 to 248
bmi = "normal weight"
case 249 to 299
bmi = "overweight"
case else
bmi="Obese"
end select

so you can rewrite the girly bit yourself

ElseIf g = female Then
If (bmiCalc < 19) Then
bmimean = "underweight"
ElseIf (bmiCalc >= 19 And bmiCalc < 23.9) Then
bmimean = "normal weight"
ElseIf (bmiCalc >= 23.9 And bmiCalc < 24) Then
bmimean = "overweight"
Else
bmimean = "obese"
End If

the last bit is about incorrect data the question is what are you if you are not a boy or a girl?

I would always load a function with the default values that is those that i have not been able to change so ...

bmi="invalid!"

is the first thing to put at the top of the function structure.

NOTE you dont have to test it it just happens to be true and what ever you can say or do with out a test will speed up your routines.

Else
bmimean = "invalid!"
End If
bmi = bmimean
End function

Im not at my machine so I cannot check the syntax of the select case at the moment, but a google for some descriptions of selet case and you should be able to work it out

bill stewart - here to talk