On 2/13/2012 3:00 PM, Ben Bacarisse wrote:
> BGB<
cr8...@hotmail.com> writes:
> <snip>
>> also, even though double has more bits than, say, an integer, does not
>> mean it will reliably encode an integer's value (it can do so in
>> theory, and will most often do so, but whether or not it will actually
>> always do so is more "up for grabs").
>
> It's not up for grabs in C (and C++ is essentially the same in this
> regard). If the integer can be represented exactly in the floating
> point type, it must be.
>
theoretically, yes.
given a double has 52 bits, and int is 32 bits, and it is possible to
convert exactly, it should always be reliable.
but, I have seen it not work exactly right, albeit in rare cases (IME,
usually on 64-bit Linux systems, generally fairly rare and when using
AMD chips IME).
I haven't seen the issue on Win64 though that I can remember, nor with
32-bit code, so I don't know.
it "might" have something to do with SSE for all I know (since 32-bit
code typically uses x87, and 64-bit typically uses SSE), or maybe
something to do with GCC, or similar.
might require researching, like trying to figure how exactly AMD chips
implement the "cvtsi2sd" and "cvtsd2si" instructions or similar... (I am
not even particularly sure which side of the conversion would have been
introducing a loss of accuracy, or if the cause could be something else
"in the middle" somewhere).
> <snip>
>> float or double to int, will generally truncate the value, yielding
>> the integer representation as rounded towards 0.
>
> That's true of the truncated value can be represented as an int. If
> not, the behaviour is undefined. For example, in the example that
> triggered this thread my implementation produces zero as the result.
>
I didn't notice that part of the thread until after I posted.
>> the result then is a tendency for an int->double->int conversion to
>> have a small chance to drop the integer value towards 0 (why? I don't
>> know exactly, but I have observed it before).
>
> If the int is "in range" you don't have a conforming C implementation.
>
could be.
all I know is I am fairly sure I have seen it happen in the past (unless
I remember seeing an issue probably with other causes, like maybe
arithmetic was being done somewhere was messing it up or similar).
I never really went and did an in depth investigation of the problem, as
it was fixed easily enough when I ran into it (and is not too much
different than other epsilon-type stuff when working with floating-point
types).
like, the whole: "if(fabs(a-b)<0.000001)" thing to compare for equality
or similar.
>> one can counteract this by fudging the value with a small epsilon
>> prior to converting back into an integer.
>>
>> say, for example (untested, from memory):
>> (v>=0)?((int)(v+0.0001)):((int)(v-0.0001));
>
> I can't see how this helps. If v is representable exactly as a double,
> the round trip has no effect so this code is not needed. Can you give me
> a use-case?
>
generally, I had seen it in my 3D engine, where in some cases integers
ended up getting converted to doubles and back, and sometimes they would
get "bumped" in this way. adding a small adjustment seemed to fix the
problem.
mostly since then I have been working under the assumption of trying to
avoid conversions to/from floating point types when possible (partly
also as I had made the past observation that these conversions have also
tended to be costly).
or such...