docster has asked for the wisdom of the Perl Monks concerning the following question:

Hello all. I probably have a simple question. I have a program that I have used a while written in visual C++ under windows. It takes a name, email, and item and adds it together then does some calulations on it to generate a 16 digit number that is pretty unique to the string. I cannot really post the code itself out here but here is the issue.

I needed to write a generator for it in perl that could calculate this same number exactly, to run from a webserver. Well I figured this would be a simple task as perl is powerful. So I "ported" the calculations over to a perl script... but, they come out wrong! It seems that the perl script gains +1 each time through which I have narrowed down to seemingly it rounding off the number through each pass and slowly creeping or drifting off. Now it could be the opposite... maybe the windows app is drifting off. But the windows app has reliably reproduced the same 16 digit number on hundreds of machines and has been in use a good while so we need perl to match the output.

Basically it would work like this looping through and then format the number into a serial at the bottom.

my $seed = "$name$email$item"; while ($seed =~/(.)/g) { $n += 1; if (uc($1) eq uc('a')) { $i = ($i + 173); } # many many lines and calulations here } my $m=sprintf("%.f",$i) ; my $trimmedNumber = substr($m, -16, 16); # trim 16 from the right. printf ("Trimmed: $trimmedNumber\n");
Seed: blabla # would loop through 6 times. Once per character.

Windows app: 2500202166709743

Perl app: 2500202166709760

There are a lot of things here. One was written and run on windows with c++, the other is written and run on linux in perl. The c++ cannot be changed as it has been in use a good while. Can I make perl cooperate or should I just stop now?

Replies are listed 'Best First'.
Re: The 16 digit number dilemma.
by swampyankee (Parson) on Feb 06, 2006 at 17:50 UTC

    My first suggestion would be to try use bigint. I suspect -- and without the C++ code can't be sure -- that your problem relates to Perl usually doing all its arithmetic in floating point (unless a pragma, such as use bigint is used).

    The other course may be to try to port the C++ to Linux.

    emc

    " When in doubt, use brute force." — Ken Thompson
      Wow thanks for all the replies ;) You have all been very patient. This is my first post here.

      I have made some progress using "bigint" and have the code actually getting exact on digits of up to 19 characters. I found that the calculations are identical until the number reaches 19 digits. The c++ is using 64bit signed ints that it says "wrap around" on overflow with arithmitic operations. So at the end of a calculation you can have a -6213077893701800743 number. Perl's would still be a +positive number therefore they do not match.

      Perl seems to keep adding straight on up so I have to reconcile that somehow after 19 digits. Sheesh how did I get here? Fun fun fun ;)

        Mask your result with a bitwise and: $result &= 0xffffffffffffffff;. You may need to do this after each operation or just at the end - depends what you are doing.


        DWIM is Perl's answer to Gödel
Re: The 16 digit number dilemma.
by Fletch (Bishop) on Feb 06, 2006 at 18:31 UTC

    Another approach might be to re-implement your C++ code as a library and then use Inline::C or the like so you're accessing the exact same underlying code from C++ or from Perl.

Re: The 16 digit number dilemma.
by japhy (Canon) on Feb 06, 2006 at 17:56 UTC
    You could just use an MD5 hexadecimal checksum.

    As for the problem, there should be no rounding errors if you're only using integers. But we can't analyze the problem without seeing the algorithm.


    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: The 16 digit number dilemma.
by BrowserUk (Patriarch) on Feb 06, 2006 at 18:29 UTC

    What type(s) are used for the equivalents of $n & $i in the C++ code? un/signed, 32/64-bit?

    And is $n a typo or used somewhere else in the code?


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: The 16 digit number dilemma.
by DrHyde (Prior) on Feb 07, 2006 at 10:11 UTC
    So let me get this right. You have an algorithm in another language which you're not going to show us, you have some perl code which doesn't produce the same results, and you expect us to fix your perl code to match this unknown algorithm. Yeah right.