I’ve got a perl script that loads data from an Excel XLS file into a database. First, it checks to see if the datetime of the value from the file already exists in the database. If it does, it checks to see if the value from the file is the same as the value that’s in the database. If they are the same, the value is skipped. If they are different, the value in the database is updated.
The code that does the comparison is:
if($dbVal != $fileVal) {
&UpdateData($id, $dt, $fileVal);
}
The problem is that sometimes, even though the two values ‘look’ the same, the comparison decides they aren’t and the update sub is executed. Below is an excerpt from a debug log. For every value from the file, it prints the db value and the file value. If the update sub gets executed, the “Updating…” line is printed:
dbVal = '68800812'; file val = '68800812'
dbVal = '66649164'; file val = '66649164'
Updating: 41248 : 01/01/2011 07:00 : 66649164
dbVal = '64975681'; file val = '64975681'
dbVal = '64037179'; file val = '64037179'
dbVal = '64095165'; file val = '64095165'
dbVal = '64917078'; file val = '64917078'
dbVal = '66584188'; file val = '66584188'
Updating: 41248 : 01/01/2011 12:00 : 66584188
So in the above snippet, there were two instances where the db val and the file val look the same but the update sub was executed anyway, meaning the comparison returned true when it looks like it should have been false.
Any thoughts/ideas?
Dave
Devel::Peek reveals the scalar type NV (float) instead of the expected IV (integer).
sprintfreveals imprecision, see Why am I getting long decimals (eg, 19.9499999999999) instead of the numbers I should be getting (eg, 19.95)?. When simply printed or used otherwise in string context, the number gets coerced to a representation with a 16 digit mantissa (20-21 if using exponential notation).Explicitely round the numbers before making a comparison,
sprintfand Math::Round are appropriate.