unsigned long to double

Discussion in 'C Programming' started by Richard Harnden, Sep 4, 2008.

  1. Hi,

    I've got a list of longs which I need to fix.

    Basically the numbers come from an unsigned long, which will wrap back
    to zero.
    I need them unwrapped.

    Also, my data will come from a database which doesn't have an unsigned
    long datatype ... they appear as long.

    Does the following actually do what I hope it does?

    #include <stdio.h>
    #include <math.h>
    #include <limits.h>

    int main(void)
    {
    long testme[] = {
    1649354396,
    -1512698780,
    -365331864,
    856092536,
    2076605992,
    -1006418300,
    191408540,
    1462864659,
    -1502144861,
    -269042670,
    910116600,
    2098697218,
    -971310087,
    325728931,
    1622242763,
    -1378801075
    };
    size_t n = sizeof(testme) / sizeof(testme[0]);
    size_t i;
    unsigned long max = ULONG_MAX;
    int wrapped = 0;
    double value;
    double prior_value = 0.0;

    for (i=0; i<n; i++)
    {
    value = testme + (wrapped * (double) max);

    if ( value < prior_value )
    {
    wrapped++;
    value += (double) max;
    }

    printf("%ld -> %g\n", testme, value);

    prior_value = value;
    }

    return 0;
    }
     
    Richard Harnden, Sep 4, 2008
    #1
    1. Advertising

  2. Richard Harnden <> writes:

    > I've got a list of longs which I need to fix.
    >
    > Basically the numbers come from an unsigned long, which will wrap back
    > to zero.
    > I need them unwrapped.
    >
    > Also, my data will come from a database which doesn't have an unsigned
    > long datatype ... they appear as long.
    >
    > Does the following actually do what I hope it does?


    Not quite (I think). It was only by reading the code I could decode
    what you intended and if the code was further off the mark I would
    have had to guess even more. I may still have guessed wrong!

    Here is what I think you are doing: you have some process that
    produces a sequence of numbers that you know to be strictly
    increasing. However, due to some code you can't change, all you see
    is the result after the sequence has been converted to a fixed-size
    signed integer (long in this case) and from these numbers you need to
    re-create the original sequence.

    You can't do this from the data you have unless you add in the
    assumption that the increments are never more than the maximum value
    of an unsigned long. Give that assumption, your code is almost
    correct but:

    > #include <stdio.h>
    > #include <math.h>
    > #include <limits.h>
    >
    > int main(void)
    > {
    > long testme[] = {
    > 1649354396,
    > -1512698780,
    > -365331864,
    > 856092536,
    > 2076605992,
    > -1006418300,
    > 191408540,
    > 1462864659,
    > -1502144861,
    > -269042670,
    > 910116600,
    > 2098697218,
    > -971310087,
    > 325728931,
    > 1622242763,
    > -1378801075
    > };
    > size_t n = sizeof(testme) / sizeof(testme[0]);
    > size_t i;
    > unsigned long max = ULONG_MAX;
    > int wrapped = 0;
    > double value;
    > double prior_value = 0.0;
    >
    > for (i=0; i<n; i++)
    > {
    > value = testme + (wrapped * (double) max);


    The value to multiply by should be max + 1. Clearly you need to write
    that as + (wrapped * ((double)max + 1)) or some such.

    > if ( value < prior_value )
    > {
    > wrapped++;
    > value += (double) max;


    and again you need (double)max + 1 here. I'd define a double holding
    (double)ULONG_MAX + 1 and use that instead of max.

    > }
    >
    > printf("%ld -> %g\n", testme, value);
    >
    > prior_value = value;
    > }
    >
    > return 0;
    > }


    There may also be problems using floating point arithmetic, especially
    if the sequence is a long one. Can you use unsigned long long instead?

    --
    Ben.
     
    Ben Bacarisse, Sep 4, 2008
    #2
    1. Advertising

  3. Richard Harnden

    viza Guest

    On Thu, 04 Sep 2008 04:02:18 -0700, Richard Harnden wrote:

    > I've got a list of longs which I need to fix.
    >
    > Basically the numbers come from an unsigned long, which will wrap back
    > to zero.
    > I need them unwrapped.
    >
    > Also, my data will come from a database which doesn't have an unsigned
    > long datatype ... they appear as long.
    >
    > Does the following actually do what I hope it does?


    Doing this in floating point is a very bad idea. On most systems double
    cannot represent all the integers in the range of long, so if you have
    large numbers they will get rounded to the nearest multiple of two or
    four or eight etc, depending on their mangitude.

    It is also much slower.

    Converting an unsigned long int to a long int produces implementation
    defined results if is outside the range of long int, so you need to test
    what the output of the system that put the numbers into the database, but
    in most cases, it is sufficient to do:

    {
    long testme= FOO;
    unsigned long corrected;

    corrected= testme;
    }

    HTH
    viza
     
    viza, Sep 4, 2008
    #3
  4. Richard Harnden

    Boon Guest

    viza wrote:

    > Doing this in floating point is a very bad idea. On most systems
    > double cannot represent all the integers in the range of long,


    Are you thinking of systems where longs are 64-bits wide?
     
    Boon, Sep 4, 2008
    #4
  5. Richard Harnden

    Guest

    viza wrote:
    > ... On most systems double
    > cannot represent all the integers in the range of long, so if you have


    I agree that you should not write code which assumes that long
    integers can be converted to double without loss of precision.
    However, I'm think that you may be overstating your case by using the
    word "most". I don't know exact numbers, but it seems to me that
    implementations with 32-bit longs are still pretty common. The
    standard permits "double" to have insufficient precision to represent
    a 32-bit integer, but I doubt that implementations where this is the
    case are common. Most implementations I'm familiar with use IEEE
    format double precision, which has nearly twice that capacity.
     
    , Sep 4, 2008
    #5
  6. On 4 Sep, 14:10, Eric Sosman <> wrote:
    > Richard Harnden wrote:
    > >     unsigned long max = ULONG_MAX;
    > >     int wrapped = 0;
    > > [...]
    > >     for (i=0; i<n; i++)
    > >     {
    > >         value = testme + (wrapped * (double) max);

    >
    >      Off by one here: The modulus is not ULONG_MAX, but one
    > greater.  (The problem might even be gnarlier, depending on
    > how the original data was transformed along its route to and
    > from your database.)


    Right, thanks. I'll do what Ben said and use a 'double max =
    (double)ULONG_MAX + 1;'

    >
    >      It looks like you started with a non-decreasing sequence
    > of numbers, but only their low-order bits have been retained.
    > So you look for places where the value steps downward instead
    > of upward, and at each such place you say "Aha! this is where
    > the lost high-order part increased."  That's fine, but how
    > do you know the lost bits increased by just one step, that
    > there was only one wrap-around?  Even between one number and
    > a larger successor there could have been wrap-around.  Unless
    > you know something about the spacing of the samples vis-a-vis
    > the rate of change of what they measure, lost is lost.
    >


    That's it exactly. A sample is taken every hour, but it could easily
    wrap-around more than once during that interval. I guess that I'll
    have to sample more frequently, especially since it's any sudden
    spurts of activity that I'm interested in.

    Thanks for your help.
     
    Richard Harnden, Sep 4, 2008
    #6
  7. Richard Harnden

    viza Guest

    On Thu, 04 Sep 2008 08:33:42 -0700, jameskuyper wrote:

    > viza wrote:
    >> On most systems double cannot represent all the integers in the
    >> range of long

    >
    > I agree that you should not write code which assumes that long integers
    > can be converted to double without loss of precision. However, I'm think
    > that you may be overstating your case by using the word "most".


    perhaps ..."most systems (that I'm sitting at)"...
    :)
     
    viza, Sep 4, 2008
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Sydex
    Replies:
    12
    Views:
    6,508
    Victor Bazarov
    Feb 17, 2005
  2. George Marsaglia

    Assigning unsigned long to unsigned long long

    George Marsaglia, Jul 8, 2003, in forum: C Programming
    Replies:
    1
    Views:
    684
    Eric Sosman
    Jul 8, 2003
  3. Daniel Rudy

    unsigned long long int to long double

    Daniel Rudy, Sep 19, 2005, in forum: C Programming
    Replies:
    5
    Views:
    1,198
    Peter Shaggy Haywood
    Sep 20, 2005
  4. CFAN
    Replies:
    6
    Views:
    827
    Tor Rustad
    Apr 4, 2007
  5. pozz
    Replies:
    12
    Views:
    746
    Tim Rentsch
    Mar 20, 2011
Loading...

Share This Page