Michael Glaesemann <[EMAIL PROTECTED]> writes: > ... I think this just confirms that there is some kind of rounding (or > lack of) in interval_div. Kind of frustrating that it's not visible > in the result.
I think the fundamental problem is that the float8 results of division are inaccurate, and yet we're assuming that we can (for instance) coerce them to integer and get exactly the right answer. For instance, in the '41 months'/10 example, I get month_remainder_days being computed as (gdb) p month_remainder $19 = 0.099999999999999645 (gdb) s 2575 result->day += (int32) month_remainder_days; (gdb) p month_remainder_days $20 = 2.9999999999999893 The only way we can really fix this is to be willing to round off the numbers, and I think the only principled way to do that is to settle on a specific target accuracy, probably 1 microsecond. Then the thing to do would be to scale up all the intermediate float results to microseconds and apply rint(). Something like (untested) month_remainder = rint(span->month * USECS_PER_MONTH / factor); day_remainder = rint(span->day * USECS_PER_DAY / factor); result->month = (int32) (month_remainder / USECS_PER_MONTH); result->day = (int32) (day_remainder / USECS_PER_DAY); month_remainder -= result->month * USECS_PER_MONTH; day_remainder -= result->day * USECS_PER_DAY; /* * Handle any fractional parts the same way as in interval_mul. */ /* fractional months full days into days */ month_remainder_days = month_remainder * DAYS_PER_MONTH; extra_days = (int32) (month_remainder_days / USECS_PER_DAY); result->day += extra_days; /* fractional months partial days into time */ day_remainder += month_remainder_days - extra_days * USECS_PER_DAY; #ifdef HAVE_INT64_TIMESTAMP result->time = rint(span->time / factor + day_remainder); #else result->time = rint(span->time * 1.0e6 / factor + day_remainder) / 1.0e6; #endif This might need a few more rint() calls --- I'm assuming that float ops with exact integral inputs will be OK, which is an assumption used pretty widely in the datetime code, but ... Per the comment, if we do this here we probably want to make interval_mul work similarly. regards, tom lane ---------------------------(end of broadcast)--------------------------- TIP 4: Have you searched our list archives? http://archives.postgresql.org