Rounding by prayer?

Discussion in 'C++' started by Steven T. Hatton, Jul 3, 2004.

  1. I'm surprised I haven't hit this situation till now, but I don't believe
    I've had to deal with it before. I have a function that sets the
    components of a point class (QPoint from Qt). It takes integer arguments
    for the components. I am calculating the values using transcendental
    functions sin and cos which return floating point type values. (The
    compiler claims they are double though I expected float in, float out.) I
    guess I have some choices as to whether I pass the floating point values
    and let the conversion take place automagically, or convert first and then
    pass the resulting integers. How is such a situation typically handled in
    C++?

    So far as I know there is no explicit round() function native to C++ that
    will round a float or double to an int or size_t. Is this correct?


    Here's a code snippet that has the actual invocation in it:
    namespace drawings
    {
    static float pi = acos(-1.0f); // not sure if static is right here.
    StarFactory::StarFactory():
    edgeLength(100.0f)
    {
    size_t n = StarFactory::NUMBER_OF_POINTS;
    this->pointArrayPtr = new QPointArray(n);
    float dTheta = 2.0f/float(n) * pi;
    float l = this->edgeLength;
    for(size_t i = 0; i < n; i++)
    {
    float theta = float(i) * dTheta;
    /*The following line is where the conversion happens*/
    this->pointArrayPtr->setPoint(i, l * cos(theta), l * sin(theta));
    }
    }

    StarFactory::~StarFactory()
    {
    /// @todo destroy me
    }
    }
    ;

    --
    STH
    Hatton's Law: "There is only One inviolable Law"
    KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
    Mozilla: http://www.mozilla.org
     
    Steven T. Hatton, Jul 3, 2004
    #1
    1. Advertising

  2. On Sat, 03 Jul 2004 04:18:37 -0400, Steven T. Hatton
    <> wrote:

    > I'm surprised I haven't hit this situation till now, but I don't believe
    > I've had to deal with it before. I have a function that sets the
    > components of a point class (QPoint from Qt). It takes integer arguments
    > for the components. I am calculating the values using transcendental
    > functions sin and cos which return floating point type values. (The
    > compiler claims they are double though I expected float in, float out.)


    You should normally use doubles. I can't see any reason not to in your
    code. Obviously doubles have more precision and greater range, but
    (apparently) on floating point hardware they are as fast as if, not
    faster, than floats. So the only reason to use floats is to save space,
    which isn't the case for your code.

    > I
    > guess I have some choices as to whether I pass the floating point values
    > and let the conversion take place automagically, or convert first and
    > then
    > pass the resulting integers. How is such a situation typically handled in
    > C++?


    I usually write a simple round function, e.g.

    int round(double x)
    {
    return static_cast<int>(d > 0 ? d + 0.5 : d - 0.5);
    }

    The 'automagic' conversion truncates towords zero, e.g.

    1.9 ==> 1
    -0.8 ==> 0

    which doesn't sound like what you want.

    >
    > So far as I know there is no explicit round() function native to C++ that
    > will round a float or double to an int or size_t. Is this correct?
    >


    Yes, presumably because there are several issues here. For instance which
    algorithm to use for rounding (the above is only one possible), and how to
    deal with overflow (which I've ignored above).

    john
     
    John Harrison, Jul 3, 2004
    #2
    1. Advertising

  3. "John Harrison" <> wrote in message
    news:eek:psajzq9mf212331@andronicus...

    > You should normally use doubles. I can't see any reason not to in your
    > code. Obviously doubles have more precision and greater range, but
    > (apparently) on floating point hardware they are as fast as if, not
    > faster, than floats. So the only reason to use floats is to save space,
    > which isn't the case for your code.


    In fact, there is a real performance difference. Once I had to write FFT
    (fast fourier transform) algorithm in C++, and version which used
    float numbers worked about 2.5 times faster than version which used
    double numbers. If it matters, PC was based on AMD Duron processor,
    and compiler was from Borland C++ Builder 5.
     
    Sergey Khoroshavin, Jul 3, 2004
    #3
  4. John Harrison wrote:


    > You should normally use doubles. I can't see any reason not to in your
    > code. Obviously doubles have more precision and greater range, but
    > (apparently) on floating point hardware they are as fast as if, not
    > faster, than floats. So the only reason to use floats is to save space,
    > which isn't the case for your code.


    I'm not even sure why I was using float there. Perhaps I just followed some
    sample code. I've found a lot of C++ stuff uses floats where I would have
    expected doubles. I will keep this issue in mind. My guess is the
    performance impact could well be sensitive to the hardware, compiler, and
    context. (ACK: I have read Sergey's response).

    > I usually write a simple round function, e.g.
    >
    > int round(double x)
    > {
    > return static_cast<int>(d > 0 ? d + 0.5 : d - 0.5);
    > }
    >
    > The 'automagic' conversion truncates towords zero, e.g.
    >
    > 1.9 ==> 1
    > -0.8 ==> 0
    >
    > which doesn't sound like what you want.


    I'm under the impression this is implementation dependent. I've only
    glanced at the discussion, but it looks like the rounding style is part of
    the descriptive datastructure required by the Standard. I'm looking at
    18.2.1
    namespace std {
    template<class T> class numeric_limits {
    public:
    static const bool is_specialized = false;
    static T min() throw();
    static T max() throw();
    static const int digits = 0;
    static const int digits10 = 0;
    static const bool is_signed = false;
    static const bool is_integer = false;
    static const bool is_exact = false;
    static const int radix = 0;
    static T epsilon() throw();
    static T round_error() throw();
    static const int min_exponent = 0;
    static const int min_exponent10 = 0;
    static const int max_exponent = 0;
    static const int max_exponent10 = 0;
    static const bool has_infinity = false;
    static const bool has_quiet_NaN = false;
    static const bool has_signaling_NaN = false;
    static const float_denorm_style has_denorm = denorm_absent;
    static const bool has_denorm_loss = false;
    static T infinity() throw();
    static T quiet_NaN() throw();
    static T signaling_NaN() throw();
    static T denorm_min() throw();
    static const bool is_iec559 = false;
    static const bool is_bounded = false;
    static const bool is_modulo = false;
    static const bool traps = false;
    static const bool tinyness_before = false;
    static const float_round_style round_style = round_toward_zero;
    };
    }
    ...

    static const float_round_style round_style;
    63 The rounding style for the type.206)

    64 Meaningful for all floating point types. Specializations for integer
    types shall return round_toward_zero.

    18.2.1.3 Type float_round_style
    namespace std {
    enum float_round_style {
    round_indeterminate = -1,
    round_toward_zero = 0,
    round_to_nearest = 1,
    round_toward_infinity = 2,
    round_toward_neg_infinity =3
    };
    }

    >>
    >> So far as I know there is no explicit round() function native to C++ that
    >> will round a float or double to an int or size_t. Is this correct?
    >>

    >
    > Yes, presumably because there are several issues here. For instance which
    > algorithm to use for rounding (the above is only one possible), and how to
    > deal with overflow (which I've ignored above).
    >
    > john


    For now I think I'll buy the quick and dirty default behavior. If I can see
    the consequence in the graphics, I'll consider a better solution.

    --
    STH
    Hatton's Law: "There is only One inviolable Law"
    KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
    Mozilla: http://www.mozilla.org
     
    Steven T. Hatton, Jul 3, 2004
    #4
  5. On Sat, 03 Jul 2004 09:01:25 -0400, Steven T. Hatton
    <> wrote:

    > John Harrison wrote:
    >
    >
    >> You should normally use doubles. I can't see any reason not to in your
    >> code. Obviously doubles have more precision and greater range, but
    >> (apparently) on floating point hardware they are as fast as if, not
    >> faster, than floats. So the only reason to use floats is to save space,
    >> which isn't the case for your code.

    >
    > I'm not even sure why I was using float there. Perhaps I just followed
    > some
    > sample code. I've found a lot of C++ stuff uses floats where I would
    > have
    > expected doubles. I will keep this issue in mind. My guess is the
    > performance impact could well be sensitive to the hardware, compiler, and
    > context. (ACK: I have read Sergey's response).


    I'm sure that's right.

    >
    >> I usually write a simple round function, e.g.
    >>
    >> int round(double x)
    >> {
    >> return static_cast<int>(d > 0 ? d + 0.5 : d - 0.5);
    >> }
    >>
    >> The 'automagic' conversion truncates towords zero, e.g.
    >>
    >> 1.9 ==> 1
    >> -0.8 ==> 0
    >>
    >> which doesn't sound like what you want.

    >
    > I'm under the impression this is implementation dependent. I've only
    > glanced at the discussion, but it looks like the rounding style is part
    > of
    > the descriptive datastructure required by the Standard. I'm looking at
    > 18.2.1


    [snip]

    >


    This is covered explicitly in 4.9 para 1, 'An rvalue of a floating point
    type can be converted to an rvalue of an integer type. The conversion
    truncates; that is, the fractional part is discarded.'


    >>>
    >>> So far as I know there is no explicit round() function native to
    >>> C++ that
    >>> will round a float or double to an int or size_t. Is this correct?
    >>>

    >>
    >> Yes, presumably because there are several issues here. For instance
    >> which
    >> algorithm to use for rounding (the above is only one possible), and how
    >> to
    >> deal with overflow (which I've ignored above).
    >>
    >> john

    >
    > For now I think I'll buy the quick and dirty default behavior. If I can
    > see
    > the consequence in the graphics, I'll consider a better solution.
    >


    john
     
    John Harrison, Jul 3, 2004
    #5
  6. Steven T. Hatton wrote:

    > guess I have some choices as to whether I pass the floating point values
    > and let the conversion take place automagically, or convert first and then
    > pass the resulting integers. How is such a situation typically handled in
    > C++?


    it's been a long, long time since i've had to do any serious math
    programming that involved converting to integers. but i seem to recall
    that standard behavour is simple truncation.

    1.1 -> 1
    1.9 -> 1
    0.1 -> 0
    0.9 -> 0

    aka rounding towards 0.

    > So far as I know there is no explicit round() function native to C++ that
    > will round a float or double to an int or size_t. Is this correct?


    i honestly can't remember, but it's easy enough to emulate:

    // not considering -ve
    double round(double d)
    {
    return (fmod(d, 1.0) > 0.5) ? ceil(d) : floor(d);
    }

    i remember once for some reason we did one that was something like this:

    // not considering -ve, this is just a vague memory
    double round(double d)
    {
    double r = fmod(fabs(d), 2.0);
    if (r >= 1.0) // odd
    {
    return (r > 1.5) ? ceil(d) : floor(d);
    }
    else // even
    {
    return (r >= 0.5) ? ceil(d) : floor(d);
    }
    }

    though i can't remember why. i think it was required by a prof. these
    days i don't exactly strive for techincal accuracy. close enough is good
    enough.

    if you want speed, and you know you're converting anyway, you might want
    to just write a conversion function.

    int double_to_int(double d)
    {
    if (fmod(fabs(d), 1.0) > 0.5)
    {
    int i = int(d);
    return i < 0 ? --i : ++i;
    }
    else
    {
    return int(d);
    }
    }

    > namespace drawings
    > {
    > static float pi = acos(-1.0f); // not sure if static is right here.


    no, not really, more like const. but have you ruled out M_PI?

    mark
     
    Mark A. Gibbs, Jul 3, 2004
    #6
  7. Sergey Khoroshavin wrote:
    > "John Harrison" <> wrote in message
    > news:eek:psajzq9mf212331@andronicus...
    >
    >>You should normally use doubles. I can't see any reason not to in your
    >>code. Obviously doubles have more precision and greater range, but
    >>(apparently) on floating point hardware they are as fast as if, not
    >>faster, than floats. So the only reason to use floats is to save space,
    >>which isn't the case for your code.

    >
    > In fact, there is a real performance difference. Once I had to write FFT
    > (fast fourier transform) algorithm in C++, and version which used
    > float numbers worked about 2.5 times faster than version which used
    > double numbers. If it matters, PC was based on AMD Duron processor,
    > and compiler was from Borland C++ Builder 5.


    One possible reason for the speed difference is that floats use less
    memory. Therefore floats are less likely to trash the cache and consume
    less memory bandwidth, which is a concern when the clockspeed of the
    processor is much higher than the memory.

    --
    Peter van Merkerk
    peter.van.merkerk(at)dse.nl
     
    Peter van Merkerk, Jul 5, 2004
    #7
  8. In message <>, Steven T. Hatton
    <> writes
    >John Harrison wrote:
    >
    >
    >> You should normally use doubles. I can't see any reason not to in your
    >> code. Obviously doubles have more precision and greater range, but
    >> (apparently) on floating point hardware they are as fast as if, not
    >> faster, than floats. So the only reason to use floats is to save space,
    >> which isn't the case for your code.

    >
    >I'm not even sure why I was using float there. Perhaps I just followed some
    >sample code. I've found a lot of C++ stuff uses floats where I would have
    >expected doubles. I will keep this issue in mind. My guess is the
    >performance impact could well be sensitive to the hardware, compiler, and
    >context. (ACK: I have read Sergey's response).
    >
    >> I usually write a simple round function, e.g.
    >>
    >> int round(double x)
    >> {
    >> return static_cast<int>(d > 0 ? d + 0.5 : d - 0.5);
    >> }
    >>
    >> The 'automagic' conversion truncates towords zero, e.g.
    >>
    >> 1.9 ==> 1
    >> -0.8 ==> 0
    >>
    >> which doesn't sound like what you want.

    >
    >I'm under the impression this is implementation dependent. I've only
    >glanced at the discussion, but it looks like the rounding style is part of
    >the descriptive datastructure required by the Standard.


    "Rounding style" refers to what it does when a calculation produces more
    digits than it can store, not how it converts float to int, which, as
    John Harrison pointed out, is well defined in 4.9.

    PS Although there's no std::round, don't overlook std::floor and
    std::ceil, which are useful for some other calculations.

    --
    Richard Herring
     
    Richard Herring, Jul 5, 2004
    #8
    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. walala
    Replies:
    12
    Views:
    1,904
  2. valentin tihomirov

    rounding to integer

    valentin tihomirov, Feb 15, 2004, in forum: VHDL
    Replies:
    2
    Views:
    9,762
    Jonathan Bromley
    Feb 16, 2004
  3. David Goodger

    The Pythonista's Prayer

    David Goodger, Oct 17, 2003, in forum: Python
    Replies:
    0
    Views:
    287
    David Goodger
    Oct 17, 2003
  4. gen_tricomi

    opensource prayer

    gen_tricomi, Mar 9, 2006, in forum: Python
    Replies:
    0
    Views:
    303
    gen_tricomi
    Mar 9, 2006
  5. Ingvar Hagelund

    A perl prayer

    Ingvar Hagelund, Jul 16, 2003, in forum: Perl Misc
    Replies:
    2
    Views:
    94
    Tony Curtis
    Jul 16, 2003
Loading...

Share This Page