Forums: » Register « |  Free Tools |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support |

New Free Tools on Dev Shed!

#1
October 19th, 2011, 07:27 AM
 hwilko123
Registered User

Join Date: Oct 2011
Posts: 1
Time spent in forums: 16 m 40 sec
Reputation 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
October 19th, 2011, 07:39 PM
 Doug G
Stumpier old Moderator

Join Date: Jun 2003
Posts: 14,370
Time spent in forums: 2 Months 2 h 16 m 22 sec
Reputation Power: 4538
Look into using SELECT .. CASE rather than lots of if statements.

Also please use the forum CODE tags when posting code snips.
__________________
======
Doug G
======
It is a truism of American politics that no man who can win an election deserves to. --Trevanian, from the novel Shibumi

#3
October 19th, 2011, 10:17 PM
 medialint
Type Cast Exception

Join Date: Apr 2004
Location: OAKLAND CA | Adam's Point (Fairyland)
Posts: 14,950
Time spent in forums: 6 Months 2 Weeks 2 Days 6 h 7 m 33 sec
Reputation Power: 8544
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.
__________________
medialint.com

“Today you are You, that is truer than true. There is no one alive who is Youer than You.” - Dr. Seuss

Last edited by medialint : October 19th, 2011 at 10:21 PM.

#4
December 7th, 2011, 05:28 PM
 the-listener
Registered User

Join Date: Dec 2011
Posts: 23
Time spent in forums: 4 h 48 m 40 sec
Reputation Power: 0
Quote:
 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

 Viewing: Dev Shed Forums > Programming Languages - More > Visual Basic Programming > Code not working