Preferred Style Question

Discussion in 'C++' started by Mike Copeland, Sep 25, 2012.

  1. What are some accepted ways to do the following calculation - and
    avoid the compiler warnings that expose conversion data loss? (I'm
    trying to compute the total time in seconds that a person has to
    complete an event, based on a stated pace.) TIA

    double dDistance = 6.214;
    time_t tPace = 600;
    time_t tEstTime;

    tEstTime = tPace * dDistance;
     
    Mike Copeland, Sep 25, 2012
    #1
    1. Advertising

  2. In article <XnsA0D9CE5D36A8Emyfirstnameosapriee@216.196.109.131>,
    says...
    > > What are some accepted ways to do the following calculation - and
    > > avoid the compiler warnings that expose conversion data loss? (I'm
    > > trying to compute the total time in seconds that a person has to
    > > complete an event, based on a stated pace.) TIA
    > >
    > > double dDistance = 6.214;
    > > time_t tPace = 600;
    > > time_t tEstTime;
    > >
    > > tEstTime = tPace * dDistance;

    >
    > Now you immediately see that the datatype for Pace is wrong - why it
    > should be time_t if it is not in seconds? It should be double as well.


    No, it's a computed "seconds mile", derived from a prompted value
    that's in "minutes per mile". That is, the user is asked for "pace",
    and the user responds in minutes. After that, the "seconds" value is
    calculated and used for numerous calculations and displays.
    >
    > OTOH, in this kind of code one can see immediately that the units are
    > used correctly. Whenever you see something like esTime_s = distance_m *
    > pace_hour_km you know there is a bug.


    That may be, but I must determine a value that is compared to a
    presented scalar value that's in "seconds". The purpose of this derived
    value is to place the user's estimate into one of 30 "slots" to
    establish groupings. I want the processing to be precise (and not use
    f/p comparisons), and I used to use "int". Now I'm trying to use a more
    appropriate "time_t" for all "seconds-based" calculations and displays.
    >
    > The conversion warning comes because you want to squeeze the floating-
    > point result into an integer, losing precision. If there are no other
    > prevailing reasons, I would say that precision loss should be avoided. As
    > we have now got rid of meaningless type prefixes, it is easy to change
    > the datatype:
    >
    > double distance_m = 6.214; // distance in meters
    > double pace_s_m = 600; // pace, in seconds per meter
    > double estTime_s = distance_m * pace_s_m; // estimated time in seconds


    Since I have to work in seconds throughout my processing, use of
    "double" isn't going to help here. I really want to produce "time_t"
    values and work from them.
     
    Mike Copeland, Sep 25, 2012
    #2
    1. Advertising

  3. Mike Copeland

    Rui Maciel Guest

    Mike Copeland wrote:

    > What are some accepted ways to do the following calculation - and
    > avoid the compiler warnings that expose conversion data loss? (I'm
    > trying to compute the total time in seconds that a person has to
    > complete an event, based on a stated pace.) TIA
    >
    > double dDistance = 6.214;
    > time_t tPace = 600;
    > time_t tEstTime;
    >
    > tEstTime = tPace * dDistance;


    As the type of dDistance is double and the typeof tPace is time_t, the
    expression "tPace * dDistance" is evaluated to an object of type double.
    Then, the result of that expression is assigned to tEstTime, which is
    another object of type time_t.

    The thing with time_t is that it is an unsigned integer type. If the
    expression "tPace*dDistance" returns a negative value then maybe all sorts
    of hell will breaks loose, as this behavior is left undefind in the
    standard.

    If, instead, the "tPace*dDistance" expression is evaluated to a positive
    number then the assignment will truncate the resulting value towards zero.
    There's not much that can be done about it, other than making sure that,
    instead of truncating it, we make sure the value is rounded. There are some
    simple[¹] and convoluted[2] suggestions floating around, but, at least since
    C99, it's possible to avoid all that with a simple call to
    nearbyint(tPace*dDistance).

    Another detail which is rarely mentioned is the possibility of a floating
    point operation having been raised, which includes the possibility of
    dDistance ending up storing an invalid value, such as NaN or divide-by-zero.
    Checking the floating point exception flags can save some headaches.

    So, data will be lost either way. You just need to make sure that dDistance
    stores a valid positive value and then assign it to tEstTime. If you can
    ensure that then it's safe to assume that the only conversion loss that can
    happen is the loss of the fractional part of your floating point value.
    Having done that then you will probably get rid of those warnings about
    conversion loss once you cast the result back to time_t. And that's about
    it.


    Hope this helps,
    Rui Maciel


    [¹] http://c-faq.com/fp/round.html
    [2] http://www.cs.tut.fi/~jkorpela/round.html
     
    Rui Maciel, Sep 25, 2012
    #3
  4. Mike Copeland

    Luca Risolia Guest

    On 25/09/2012 18:39, Mike Copeland wrote:
    > What are some accepted ways to do the following calculation - and
    > avoid the compiler warnings that expose conversion data loss? (I'm
    > trying to compute the total time in seconds that a person has to
    > complete an event, based on a stated pace.) TIA
    >
    > double dDistance = 6.214;
    > time_t tPace = 600;
    > time_t tEstTime;
    >
    > tEstTime = tPace * dDistance;


    #include <chrono>
    #include <ratio>
    #include <iostream>

    typedef long double meters;
    meters operator"" _m(const long double x) { return x; }
    meters operator"" _km(const long double x) { return x * 1000; }

    std::chrono::seconds operator"" _s_per_m(unsigned long long x) {
    return std::chrono::seconds(x);
    }

    template<typename V, typename R>
    std::eek:stream& operator << (std::eek:stream& o,
    const std::chrono::duration<V, R>& d) {
    return o << d.count() << " ticks of "
    << R::num << '/' << R::den << " seconds";
    }

    int main() {
    auto distance = 6.214_m;
    auto pace = 600_s_per_m;
    auto estTime = pace * distance;
    std::cout << estTime << '\n';
    // 3728.4 ticks of 1/1 seconds (= 3728,4 seconds)
    }
     
    Luca Risolia, Sep 26, 2012
    #4
  5. On Sep 25, 8:06 pm, (Mike Copeland) wrote:
    > In article <XnsA0D9CE5D36A8Emyfirstnameosapr...@216.196.109.131>,
    > says...



    > > >    What are some accepted ways to do the following calculation - and
    > > > avoid the compiler warnings that expose conversion data loss?  (I'm
    > > > trying to compute the total time in seconds that a person has to
    > > > complete an event, based on a stated pace.)  TIA

    >
    > > >   double dDistance = 6.214;
    > > >   time_t tPace     = 600;
    > > >   time_t tEstTime;

    >
    > > >   tEstTime = tPace * dDistance;

    >
    > > Now you immediately see that the datatype for Pace is wrong - why it
    > > should be time_t if it is not in seconds? It should be double as well.

    >
    >    No, it's a computed "seconds mile", derived from a prompted value
    > that's in "minutes per mile".  That is, the user is asked for "pace",
    > and the user responds in minutes.  After that, the "seconds" value is
    > calculated and used for numerous calculations and displays.
    >
    > > OTOH, in this kind of code one can see immediately that the units are
    > > used correctly. Whenever you see something like esTime_s = distance_m*
    > > pace_hour_km you know there is a bug.

    >
    >    That may be, but I must determine a value that is compared to a
    > presented scalar value that's in "seconds".  The purpose of this derived
    > value is to place the user's estimate into one of 30 "slots" to
    > establish groupings.  I want the processing to be precise (and not use
    > f/p comparisons),


    this makes no sense. How does cramming the result into one of 30
    integral bins make the result "precise"? There's a floating point
    value in there so the result is going to be a floating point value.

    > and I used to use "int".  Now I'm trying to use a more
    > appropriate "time_t" for all "seconds-based" calculations and displays.
    >
    > > The conversion warning comes because you want to squeeze the floating-
    > > point result into an integer, losing precision. If there are no other
    > > prevailing reasons, I would say that precision loss should be avoided. As
    > > we have now got rid of meaningless type prefixes, it is easy to change
    > > the datatype:

    >
    > > double distance_m = 6.214; // distance in meters
    > > double pace_s_m = 600; // pace, in seconds per meter
    > > double estTime_s = distance_m * pace_s_m; // estimated time in seconds

    >
    >    Since I have to work in seconds throughout my processing, use of
    > "double" isn't going to help here.  I really want to produce "time_t"
    > values and work from them.


    why?
     
    Nick Keighley, Sep 26, 2012
    #5
  6. On Sep 26, 3:05 pm, (Scott Lurndal) wrote:
    > Paavo Helde <> writes:
    > > (Mike Copeland) wrote in
    > >news:-september.org:

    >
    > >> I want the processing to be precise (and not
    > >> use f/p comparisons), and I used to use "int".

    >
    > >What you mean by "precise"? Double typetype is quite precise (ca 10^-16)..
    > >If a  floating-point algorithm using double does not yield the same
    > >results to at least 10 decimal places on all platforms, then the
    > >algorithm is arguably broken.

    >
    > Actually, one cannot represent 0.1 in binary floating point with exact
    > precision - the binary version is a non-terminating, infinite expansion;
    > rounded to 24 bits, it's 0.100000001490116119384765625 in decimal.


    actually you *can* represent 0.1 to at least 10 decimal places, which
    is what he said. Which sounds plenty to me. Do runners really time
    themselves to the nearest millisecond?

    > The new decimal floating point supported by the latest C standard
    > (and implemented in gcc) should provide more accurate and precise
    > calculations (albiet much more slowly).
    >
    > IEEE compliant hardware will ensure that a binary floating result will
    > be accurate within 0.5 of the "unit in the last place".
     
    Nick Keighley, Sep 27, 2012
    #6
  7. "Scott Lurndal" wrote in message news:IYD8s.183055$...
    >
    >Paavo Helde <> writes:
    >> (Mike Copeland) wrote in
    >>news:-september.org:
    >>
    >>> I want the processing to be precise (and not
    >>> use f/p comparisons), and I used to use "int".

    >>
    >>What you mean by "precise"? Double typetype is quite precise (ca 10^-16).
    >>If a floating-point algorithm using double does not yield the same
    >>results to at least 10 decimal places on all platforms, then the
    >>algorithm is arguably broken.

    >
    >Actually, one cannot represent 0.1 in binary floating point with exact
    >precision - the binary version is a non-terminating, infinite expansion;
    >rounded to 24 bits, it's 0.100000001490116119384765625 in decimal.


    Note that the approximation of 0.1 with an binary integer type is much less
    accurate.
     
    Fred Zwarts \(KVI\), Sep 27, 2012
    #7
  8. "Scott Lurndal" wrote in message news:TKZ8s.85461$...
    >
    >"Fred Zwarts \(KVI\)" <> writes:
    >>"Scott Lurndal" wrote in message =
    >>news:IYD8s.183055$...
    >>>
    >>>Paavo Helde <> writes:
    >>>> (Mike Copeland) wrote in
    >>>>news:-september.org:
    >>>>
    >>>>> I want the processing to be precise (and not
    >>>>> use f/p comparisons), and I used to use "int".
    >>>>
    >>>>What you mean by "precise"? Double typetype is quite precise (ca =

    >>10^-16).
    >>>>If a floating-point algorithm using double does not yield the same
    >>>>results to at least 10 decimal places on all platforms, then the
    >>>>algorithm is arguably broken.
    >>>
    >>>Actually, one cannot represent 0.1 in binary floating point with exact
    >>>precision - the binary version is a non-terminating, infinite =

    >>expansion;
    >>>rounded to 24 bits, it's 0.100000001490116119384765625 in decimal.

    >>
    >>Note that the approximation of 0.1 with an binary integer type is much =
    >>less=20
    >>accurate.=20
    >>

    >
    >
    >Not if you scale it by, say 100.
    >
    >scott


    If you scale it, then also the floating point representation will be exact.
     
    Fred Zwarts \(KVI\), Sep 27, 2012
    #8
  9. "Mike Copeland" wrote in message
    news:-september.org...
    >
    > I want the processing to be precise (and not use >f/p comparisons),


    I think that it is a misconception that floating point type are not precise.
    They are as precise as integer types. One of the first computers I worked
    with, had no integer arithmetic in hardware, only floating point arithmetic.
    Integer arithmetic operation in high level languages were performed using
    floating point operations.

    Take as an example an integer type using N bits (including sign bit). Also
    take a floating point type using N bits for the mantissa (including sign
    bit). Then each value that can be represented by the integer type can also
    be represented EXACTLY by the floating point type. Further, the arithmetic
    integer operations (+, -, *, /) can be mapped to floating point operations
    that yield EXACTLY the same represented value (as long as the result can
    still be represented with N bits). (The most complex one is the integer
    divide operation, which maps to a floating point divide followed by a
    truncation.)
    So, if the floating point type can map EXACTLY all the integer type values
    and all integer arithmetic operations, it is simply not true that floating
    point types are less precise than integer types.

    Why then do we use integer and floating point types. Not because of
    precision, but because of other features:

    *) Integer types have other operations (like bit shifting, bit-wise logical)
    that floating point types have not.

    *) Floating point types yield rounded results when the result of an
    operation exceeds the minimum or maximum that can be represented with N
    bits, whereas an integer type will have an undefined result.

    *) Floating point types have an automatic scale factor, to make it easier to
    work with very big, or with very small numbers. (A problem is that this
    scale factor is usually limited to powers of two.)

    *) Many processors have hardware integer instructions that perform better
    that the equivalent floating point instructions.

    So, floating point types are as exact as integer types (given that there are
    enough bits). The confusion arises because many people do not understand the
    floating point representation and the corresponding floating point
    operations very well. Some people think that floating point numbers can be
    used to map real numbers (in some languages this is even suggested by the
    name of the type), but that is not true. It is not even a very good mapping
    of rational numbers.
     
    Fred Zwarts \(KVI\), Sep 28, 2012
    #9
    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. Kevin Buchan
    Replies:
    1
    Views:
    506
    Eric Lawrence [MSFT]
    Feb 20, 2004
  2. Rusty Owens

    Preferred IDE

    Rusty Owens, May 10, 2004, in forum: ASP .Net
    Replies:
    14
    Views:
    844
    Samuel Hon
    May 12, 2004
  3. Rod

    Preferred way of passing data

    Rod, Aug 25, 2004, in forum: ASP .Net
    Replies:
    5
    Views:
    1,594
    Anon-E-Moose
    Aug 26, 2004
  4. Ryan Moore

    Preferred Client Side Calls

    Ryan Moore, Oct 18, 2004, in forum: ASP .Net
    Replies:
    3
    Views:
    383
    =?Utf-8?B?QWxhbiBC?=
    Oct 18, 2004
  5. Ken Varn
    Replies:
    0
    Views:
    538
    Ken Varn
    Apr 26, 2004
Loading...

Share This Page