#1
  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. #2
  3. No Profile Picture
    Grumpier old Moderator
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jun 2003
    Posts
    14,453
    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.
    ======
    Doug G
    ======
    Bartender to Rene Descartes "have another beer?" Descartes: "I think not" and he vanished.
    --Alfred Bester
  4. #3
  5. Type Cast Exception
    Devshed Supreme Being (6500+ posts)

    Join Date
    Apr 2004
    Location
    OAKLAND CA | Adam's Point (Fairyland)
    Posts
    14,954
    Rep Power
    8617
    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 10:21 PM.
    medialint.com

    “Today you are You, that is truer than true. There is no one alive who is Youer than You.” - Dr. Seuss
  6. #4
  7. 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)

    you asked ...
    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
    much easier to read

    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

IMN logo majestic logo threadwatch logo seochat tools logo