in reply to Unwanted implicit conversion to float

I suppose there are a variety of ways to handle this. One of the most straightforward would be the following:
$val += sprintf( "%.2f", $1 );
I think that should take care of that. My only concern would be the potential for rounding errors, if any of the numbers that you are matching against have more than two digits after the decimal point. In that case, you might want to just do the sprintf at the end.

If anyone sees a problem with this approach, speak up! I've used it before and would love to know if I boo-booed.

Cheers,
Ovid

Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Replies are listed 'Best First'.
Re: (Ovid) Re: Unwanted implicit conversion to float
by mirod (Canon) on Mar 12, 2001 at 23:06 UTC

    I see just a (maybe null) risk in the fact that you still add 2 floating numbers, even if $1 has been rounded to 2 digits after the decimal point. So something weird can still happen with the result. After all turnstep's original code only added such numbers. So you could end up every now and then with "long numbers".

    Doing $val= sprintf( "%.2f", $val + $1); removes the problem, $val is _always_ rounded properly. The cleanest way is of course to keep $val as is and to round it only when printing it.

    This may just be nitpicking but as I have no idea of the conditions that create the problem and it is probably quite hard to reproduce, I would not take any chance.

      The cleanest way is of course to keep $val as is and to round it only when printing it.

      Perhaps I misunderstand what you mean by "clean", but the safest way to deal with money is to round the internal number any time you print something out1, and use that rounded number for all future calculations. If you are doing calculations with only whole-cent amounts (such as adding up a bunch of deposits), then you should round after every operation (or at least frequently) to prevent tiny round-off errors from accumulating such that your final total is off by one cent when it is finally rounded.

      If you are doing calculations with fractional cents, then you need to define exactly where the rounding occurs (for example, interest is applied one a month and is always rounded at that time).

      1 Update: The reason I say "every time you print something out" is that you (almost always) need to round if the value is being reported to the user. You can (and often should) do internal, intermediate calculations in fractional cents, but whenever you report [or could report] an amount to the user, you need to round your internal representation of that amount the same way you [would] round the amount you [could] report.

              - tye (but my friends call me "Tye")

        Perhaps I misunderstood what I meant by that!

        You are right in this context of course. The round-off errors here are totally unwanted and should be fixed as early as possible.

        So the best solution is to work in cents as merlyn suggests as long as we are performing only additions (the error does not happen) and to use sprintf as early as possible and to work with the rounded value when dealing with more elaborate calculations.

        Keeping the value as-is and rounding only the printed one is only valid in a scientific context, where the real number is too long to be printed but further calculation should be based on it and not on the rounded value.