The Amazing Age Calculation Algorithm



  • Found this in our mission critical app, left behind by the original enterprise business IT graduate guru.

     It calculates the age of a patient.......<FONT size=2>

    _AgeAtProcedure = </FONT><FONT color=#0000ff size=2>CInt</FONT><FONT size=2>(DateDiff(DateInterval.Year, _BookingStartTime, _DateOfBirth, , )) </FONT>

    <FONT size=2>I'm thinking maybe I should find a new job before somebody dies.</FONT><FONT color=#008000 size=2>

    </FONT>


  • Aside from the possibility that the calculation may be off by a year in either direction (and the theoretical loss of precision from converting long -> int), what should we be seeing here?

     Granted, even just those two things should be unacceptable in a "mission critical" app for a healthcare provider.



  • @Saladin said:

    (and the theoretical loss of precision from converting long -> int)

    Wouldn't you need to have patients older than MAXINT years before this became a problem? 



  • @Malfactor said:

    It calculates the age of a patient.......

    _AgeAtProcedure = CInt(DateDiff(DateInterval.Year, _BookingStartTime, _DateOfBirth, , ))

    As far as I can tell, the DateDiff function does do the correct job of calculating the number of whole years between the two dates given. There is no WTF here. (See MSDN for more info on this function).

    The only thing I can see being wrong in any way is ensuring that the dates are the right way around. According to the documentation, the function calculates (date2 - date1), then converts the value into the units requested. If you have the parameters in the wrong order, you'll get a negative value.

    Therefore, the code is very nearly correct, and only needs a single change to make it right:

    _AgeAtProcedure = CInt(<font color="#ff0000">Math.Abs(</font>DateDiff(DateInterval.Year, _BookingStartTime, _DateOfBirth, , )<font color="#ff0000">)</font>)
     



  • @eimaj2nz said:

    As far as I can tell, the DateDiff function does do the correct job of calculating the number of whole years between the two dates given. There is no WTF here. (See MSDN for more info on this function). 

    From MSDN

    Larger Intervals. If Interval is set to DateInterval.Year, the return value is calculated purely from the year parts of Date1 and Date2.

    For the age of a person, using datediff is just plain wrong.



  • congrats.  you found a bug.  Just fix it.  That's what your paid to do.



  • ..

     

    ...

     

    Is that the VB CInt? The one that produces:

    print CInt(0.5)
    0
    print CInt(1.5)
    2



  • @Daid said:

    Is that the VB CInt? The one that produces:

    print CInt(0.5)
    0
    print CInt(1.5)
    2

      
    You mean "The one that uses bankers' rounding by default"?  Yes,
    that's the one.  It's a good default.   Think about it:
    which would you rather have - 

      a)  Advanced scientific calculations always come out right but your bank keeps losing money from your account.

     
    b)  Your bank gets your account balance right every single time
    they do their end-of-day calculations, and only once in a while does a
    NASA rocket blow up.

       It's just a question of which you think is more likely to affect you personally most often!

    [  n.b. If you are both a NASA astronaut and poverty-stricken, your mileage may vary ... ]



  • @Licky Lindsay said:

    @Saladin said:
    (and the theoretical loss of precision from converting long -> int)

    Wouldn't you need to have patients older than MAXINT years before this became a problem? 

    Yeah, that's why I said "theoretical" loss of precision :P



  • @tster said:

    congrats.  you found a bug.  Just fix it.  That's what your paid to do.

    It's not really a bug. A bug implies something that at first looks correct but turns out to be subtly wrong.

     This is just plain wrong. If I told you I was born in 1982, could you tell me how old I am today? No, and neither can a computer.



  • Bankers' rounding and "normal" rounding are a real pain in the butt.  Especially when you expect "normal" rounding for a "bank" application, and you get the other.  Imagine, if you will, what happens when you have 5 places of precision, and the 3rd place rounds "funny", and you have to figure out why some numbers in a generated table are right, while others are wrong.  In a 10-factor computation.

    Blah.  Makes me sick to think of the time.

    Better to KNOW that something works right.  And that date subtraction doesn't work right.

     



  • @DaveK said:

    @Daid said:

    Is that the VB CInt? The one that produces:

    print CInt(0.5)
    0
    print CInt(1.5)
    2

      
    You mean "The one that uses bankers' rounding by default"?  Yes,
    that's the one.  It's a good default.   Think about it:
    which would you rather have - 

      a)  Advanced scientific calculations always come out right but your bank keeps losing money from your account.

     
    b)  Your bank gets your account balance right every single time
    they do their end-of-day calculations, and only once in a while does a
    NASA rocket blow up.

       It's just a question of which you think is more likely to affect you personally most often!

    [  n.b. If you are both a NASA astronaut and poverty-stricken, your mileage may vary ... ]

    I rather not have my bank use VB to calculate my money at all. Nor floating point calculations. But you're saying that the use of VB is limited to writing bank applications?

    CInt sounds like a function that would "Convert to Int" I would say. Ok, it rounds, fine with me. But why like that, as default, without any replacement that does what you want. (int() rounds down, round() rounds in the same way as CInt).



  • @savar said:

    @tster said:

    congrats.  you found a bug.  Just fix it.  That's what your paid to do.

    It's not really a bug. A bug implies something that at first looks correct but turns out to be subtly wrong.

     This is just plain wrong. If I told you I was born in 1982, could you tell me how old I am today? No, and neither can a computer.

    bug: Informal. a defect or imperfection, as in a mechanical device, computer program, or plan; glitch: The test flight discovered the bugs in the new plane.

     

    So, yes, it is a bug. Change DateInterval.Year to DateInterval.Day and it's fixed. I think the fact that it involves changing one word more than shows that it is in fact a bug, even by your definition. At most, it is 1 year greater.

     

    Edit: So this was wrong. I just read the MSDN link, and the first doesn't give a level of precision, it gives what you want a count of. 



  • @jimlangrunner said:

    Bankers' rounding and "normal" rounding are a real pain in the butt.  Especially when you expect "normal" rounding for a "bank" application, and you get the other.  Imagine, if you will, what happens when you have 5 places of precision, and the 3rd place rounds "funny", and you have to figure out why some numbers in a generated table are right, while others are wrong.  In a 10-factor computation.

    Blah.  Makes me sick to think of the time.

    Better to KNOW that something works right.  And that date subtraction doesn't work right.

    As a programmer, it's up to you to know what type of rounding the library you've chosen is going to use.  If you're ignorant something so basic about the math functions you're using, that doesn't make the library bad, that makes you a bad programmer.

     
     



  • @sycro said:

    @savar said:

    @tster said:

    congrats.  you found a bug.  Just fix it.  That's what your paid to do.

    It's not really a bug. A bug implies something that at first looks correct but turns out to be subtly wrong.

     This is just plain wrong. If I told you I was born in 1982, could you tell me how old I am today? No, and neither can a computer.

    bug: Informal. a defect or imperfection, as in a mechanical device, computer program, or plan; glitch: The test flight discovered the bugs in the new plane.

     

    So, yes, it is a bug. Change DateInterval.Year to DateInterval.Day and it's fixed. I think the fact that it involves changing one word more than shows that it is in fact a bug, even by your definition. At most, it is 1 year greater.

     

    Edit: So this was wrong. I just read the MSDN link, and the first doesn't give a level of precision, it gives what you want a count of. 

     

    Outuput from sample: -47

    Module Module1

        Sub Main()
            Console.WriteLine(CInt(DateDiff(DateInterval.Year, DateTime.Now, DateTime.Parse("06/15/1960"), , )))
            Console.ReadLine()
        End Sub

    End Module



  • @mrsticks1982 said:

    Outuput from sample: -47

    Module Module1

        Sub Main()
            Console.WriteLine(CInt(DateDiff(DateInterval.Year, DateTime.Now, DateTime.Parse("06/15/1960"), , )))
            Console.ReadLine()
        End Sub

    End Module

    Ahhh...there it is. :D



  • @merreborn said:

    If you're ignorant something so basic about the math functions you're using, that doesn't make the library bad, that makes you a bad programmer.

    As a programmer you expect the very basic functions of the language you use to be basic functions, not to be specialized functions for banking. 



  • mmm..Cint rounds for a good reason, because int in VB are plain int, no decimal places, so it has to do something with decimal....

     

    rounds doesn't work the same way, it rounds diferents for negatives numbers...

     besides you found a bug, the code is not wrong, unless you mixed up the dates... it's really very important for a doctor if you have 34 or 35????
     


Log in to reply