Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Calculating base difference of numbers

by Anonymous Monk
on May 30, 2008 at 19:23 UTC ( #689319=perlquestion: print w/ replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I'm looking at the difference between currency exchange rate updates.

Take for example the price change from 1.5553 to 1.5552 In trading terms I can see this is a difference of 1 point since I have a pre-conceived interpretation of the numbers and how they move.

Sometimes my platform gets sent updates that drop trailing 0's after a decimal point.

e.g. '100.20' is shown as '100.2', likewise '100.00' is shown as '100'.

So how does one work out the point movement from 0.9984 -> 0.998 or 100.25 -> 100.3?

Other than converting the number to a string, calculating the number of decimal places (as x) in both rates and then multiplying the rate by 10^x (where x is the higher count of decimal places between two rates), minus rate 2 from rate 1 and then divide this resulting value by 10^(x-1)......is there an easier way...or more specifically a better performing way (mathematical)?


Thanks for any input.

Comment on Calculating base difference of numbers
Re: Calculating base difference of numbers
by toolic (Chancellor) on May 30, 2008 at 19:44 UTC
    printf can be used to format numbers to a specified number of decimal places. For example, this will give you 5 decimal places:
    printf "%.5f\n", (1.5553 - 1.5552); printf "%.5f\n", (0.9984 - 0.998); printf "%.5f\n", (100.25 - 100.3);

    prints:

    0.00010 0.00040 -0.05000
      printf in the instance you have shown doesn't give me anything I can work with
      I should have mentioned that the rates are comming in live 24/7 and I want to look at the base point movement as the rates change.
      In the examples above I'm looking to see the base point movements of +1,+4 and -5.
      Whatever solution I have to get this number must be simple enough that I can use in a function where any number with any number of decimal places is looked at and the difference to last known rate instance is calculated.

        I don't understand why you can't simply use subtraction, regardless of the decimal truncation in either of the operands.

        You're going to end up with some floating-point drift anyway; perhaps it would be a good idea to drop the decimal points and treat everything as integers, then divide by 10n when it's time to display the number to the user. (This is the recommended way of doing currency calculations so floating point error doesn't mess with your cents.)

        In the examples above I'm looking to see the base point movements of +1,+4 and -5.

        I'm not really sure I understand, but maybe something like this?

        #!/usr/bin/perl use strict; use warnings; print base_point_movement($_),"\n" for ( 1.5553 - 1.5552, 0.9984 - 0.998, 100.25 - 100.3, ); sub base_point_movement { my $diff = shift; (sprintf "%+e", $diff) =~ /([+-]\d)\./; return $1; }

        Output:

        +1 +4 -5

        Update: as has been pointed out, this only works for +/-9 — which is not too surprising, as it just extracts the before-comma digit of the difference in exponential floating-point representation  (not knowing what a "base point" is defined as, I figured it might suffice...).

        Anyhow, here's another variant, kind of extending the idea to what might have been meant — though honestly, I don't have the foggiest whether that's what the OP had in mind.  (Of course, this will also run into problems when the number of significant digits exceeds floating-point precision.)

        sub base_point_movement { my $bpm = sprintf "%+e", shift; $bpm =~ s/0*e.*$//; $bpm =~ tr/.//d; return $bpm; } print base_point_movement($_),"\n" for ( 1.5553 - 1.5552, # +1 1.5553 - 1.55, # +53 1.56 - 1.55, # +1 155.53 - 155.52, # +1 15553 - 15552, # +1 1555300 - 1555200, # +1 1555300 - 155520, # +139978 1555.300 - 1555.20, # +1 1555300 - 1555201, # +99 1.5553 - 1.555201, # +99 1.5553 - 1.55521, # +9 1.5553 - 1.555301, # -1 1.5553 - 1.55530101, # -101 1.5553 - 1.5553101, # -101 15553 - 15552.9999, # +1 15553.001 - 15552.999, # +2 15553.001 - 15552.9999, # +11 15553.1 - 15552.99, # +11 # etc. (you get the idea :) );
Re: Calculating base difference of numbers
by pc88mxer (Vicar) on May 31, 2008 at 17:01 UTC
    Are we talking about basis points? Mathematically they are defined simply as 1/100-th of 1% or .0001.
      Yes...and I feel stupid that I can't work it out...should be a simple mathematical equation.
        my $diff = ($new*10000) - ($old*10000);
        Or if you want to round it,
        my $diff = 0 + sprintf '%.0f', ($new*10000) - ($old*10000);

        Update: The *10000 can be factored out: ($new-$old)*10000

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://689319]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (9)
As of 2014-09-22 19:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (198 votes), past polls