Strange results when converting NSDate timeIntervalSinceReferenceDate to NSPoint

  • Hi,

    I need to convert NSDate to a meaningful NSPoint for the x-Axis of my
    plotting application, so that the graph plots
    the points to the corresponding time of the current day. The
    application itself is a data acquisition app which acquires
    every 0.5 seconds data from a digital Multimeter connected on the USB
    port.

    For Plotting / Graphing I'm using the excellent SM2DGraphView open-
    source plotting framework:
    http://developer.snowmintcs.com/frameworks/sm2dgraphview/

    But I get strange results when converting NSDate
    timeIntervalSinceReference to NSPoint.

    Example:

    [code]
    ------------------------------------------------------------------------
    -----------------------------------------------------

    NSPoint *graphData

    for ( iRow = 0; iRow < curRow ; iRow++ )
          {
              // map the NSDate to a meaningful X co-ordinate.
              graphData[iRow].x = [ k2700_str[iRow].acqDate
    timeIntervalSinceReferenceDate ];

    // Store the voltage value of the multimeter to
              graphData[iRow].y = k2700_str[iRow].channel;

    NSLog(@"acqDate as timeIntervalSRDate: %f | graphData.x = %f ",
    [ k2700_str[iRow].acqDate
      timeIntervalSinceReferenceDate ], graphData[iRow].x );
    }

    [/code]
    ------------------------------------------------------------------------
    -----------------------------------------------------

    [Result]

    2007-01-26 18:09:30.599 AcquiKeithley[11852] acqDate as timeInterval:
    191524170.000177 | graphData.x = 191524176.000000  =============>
    different value !!!!

    2007-01-26 18:09:30.600 AcquiKeithley[11852] acqDate as timeInterval:
    191524170.500054 | graphData.x = 191524176.000000  =============>
    different value !!!!

    [Result]

    So you see I get a different values. I tried to do a cast to (float)
    but it didn't work.
    I'm sure that I'm making something wrong.... :-(

    Does anyone have any clues ?

    Any help greatly appreciated. Thanks.

    Gilles Celli
  • Gilles Celli wrote on Saturday, January 27, 2007:
    > I need to convert NSDate to a meaningful NSPoint for the x-Axis of my
    > plotting application, so that the graph plots
    > the points to the corresponding time of the current day.
    <clip>
    >
    > [Result]
    >
    > 2007-01-26 18:09:30.599 AcquiKeithley[11852] acqDate as timeInterval:
    > 191524170.000177 | graphData.x = 191524176.000000  =============>
    > different value !!!!
    >
    > 2007-01-26 18:09:30.600 AcquiKeithley[11852] acqDate as timeInterval:
    > 191524170.500054 | graphData.x = 191524176.000000  =============>
    > different value !!!!
    >
    > [Result]
    >
    > So you see I get a different values. I tried to do a cast to (float)
    > but it didn't work.
    > I'm sure that I'm making something wrong.... :-(

    I'm certainly not an expert on floating point numbers, but I think the answer is simple: NSDates use doubles (64 bit floating point values) and NSPoint uses floats (32 bit floating point values).

    A (single) float has 23 bits for the mantissa (the significant digits). That gives you an accuracy of about 7 decimal places. The double number you are trying to convert is 191524170.500054. The first 7 digits are 1915241xx.xxxx; the rest will be lost in conversion.

    Since the origin of your graph probably isn't the reference date, the simple solution is to make the origin of your graph some recent date. Then x coordinates would be expressed as the difference between the graph's origin and the sample point, which is going to be a much smaller number. The smaller the number, the better the accuracy of the double to float conversion.

        (typed in mail)

        NSDate* graphOriginDate = [NSDate ...]; // date of x axis origin
        ...
        for (...)
            {
            graphData[iRow].x = (float)[k2700_str[iRow].acqDate timeIntervalSinceDate:graphOrginDate];
            ...
            }

    --
    James Bucanek
  • James,

    Thanks a lot for your answer. It works as you described: I had to
    take the current Date as reference Date.

    I wrote your answer and the solution on the SM2DGraphView forums:
    http://www.snowmintcs.com/forums/viewtopic.php?p=3807#3807

    Thanks for all your help.

    Gilles Celli

    On Jan 27, 2007, at 5:07 PM, James Bucanek wrote:

    >
    > I'm certainly not an expert on floating point numbers, but I think
    > the answer is simple: NSDates use doubles (64 bit floating point
    > values) and NSPoint uses floats (32 bit floating point values).
    >
    > A (single) float has 23 bits for the mantissa (the significant
    > digits). That gives you an accuracy of about 7 decimal places. The
    > double number you are trying to convert is 191524170.500054. The
    > first 7 digits are 1915241xx.xxxx; the rest will be lost in
    > conversion.
    >
    > Since the origin of your graph probably isn't the reference date,
    > the simple solution is to make the origin of your graph some recent
    > date. Then x coordinates would be expressed as the difference
    > between the graph's origin and the sample point, which is going to
    > be a much smaller number. The smaller the number, the better the
    > accuracy of the double to float conversion.
    >
    > (typed in mail)
    >
    > NSDate* graphOriginDate = [NSDate ...]; // date of x axis origin
    > ...
    > for (...)
    > {
    > graphData[iRow].x = (float)[k2700_str[iRow].acqDate
    > timeIntervalSinceDate:graphOrginDate];
    > ...
    > }
    >
    > --
    > James Bucanek
    >
previous month january 2007 next month
MTWTFSS
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
Go to today