casting constant value from float to unsigned short - compiler bugs?

N

news.aon.at

Hello,

I try to cast a constant value (-32766.5) to float and then to an unsigned
short.
Once directly and once with an intermediate variable.

unsigned short s=(unsigned short)((float)(-32766.5));

vs.

float f=((float)(-32766.5));
unsigned short s=(unsigned short)f;

I use different compilers for this:

a) IBM Visual Age 3.5 (very old, 1995)
b) Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for
80x86 (MS-C6)
c) Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for
80x86 (VS2010)
d) gcc version 2.95.2-6 19991024 (cygwin experimental)
e) mingw32-gcc (GCC) 3.4.5 (mingw special) [Copyright (C) 2004 Free Software
Foundation, Inc.]
f) WindRiver Vxw6.7 CrossCompiler: ccpentium (Wind River VxWorks G++
DWARF-EH 4.1-131) 4.1.2 [Copyright (C) 2006 Free Software Foundation, Inc.]

a,b,c,d : give 0x8002 in both cases.

e,f give 0 (!) in the first case and 0x8002 in the 2nd cases

??

Note : when i cast to a SHORT instead of an unsigned short in the first
case, ALL compilers give 0x8002
(cast to float to short to unsigned short)

unsigned short s=(short)((float)(-32766.5));
or
unsigned short s=(unsigned short)(short)((float)(-32766.5));

Any Comments?
 
J

jacob navia

Le 02/12/11 10:06, news.aon.at a écrit :
Note : when i cast to a SHORT instead of an unsigned short in the first
case, ALL compilers give 0x8002
(cast to float to short to unsigned short)

unsigned short s=(short)((float)(-32766.5));
or
unsigned short s=(unsigned short)(short)((float)(-32766.5));

Any Comments?

Yes. The first one is that the range for unsigned short is
zero to USHORT_MAX. Your program has undefined behavior
since a negative value will not go into an unsigned short,
it is OUTSIDE its domain.

Using lcc-win (Macintosh version) I obtain:

~/tmp $ cat casting.c
#include <stdio.h>
int main(void)
{
unsigned short s=(unsigned short)((float)(-32766.5));
float f = -32766.5;
short s1 = (short)f;
printf("%g\n%d 0x%x\n%d 0x%x\n",f,s,s,s1,s1);
}
~/tmp $ lcc casting.c
Warning ~/tmp/casting.c: 4 overflow in constant expression
0 errors, 1 warning
~/tmp $ ./casting
-32766.5
32770 0x8002
-32766 0xffff8002
~/tmp $
 
J

James Kuyper

Hello,

I try to cast a constant value (-32766.5) to float and then to an unsigned
short.
Once directly and once with an intermediate variable.

unsigned short s=(unsigned short)((float)(-32766.5));

vs.

float f=((float)(-32766.5));
unsigned short s=(unsigned short)f;

I use different compilers for this:

a) IBM Visual Age 3.5 (very old, 1995)
b) Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for
80x86 (MS-C6)
c) Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for
80x86 (VS2010)
d) gcc version 2.95.2-6 19991024 (cygwin experimental)
e) mingw32-gcc (GCC) 3.4.5 (mingw special) [Copyright (C) 2004 Free Software
Foundation, Inc.]
f) WindRiver Vxw6.7 CrossCompiler: ccpentium (Wind River VxWorks G++
DWARF-EH 4.1-131) 4.1.2 [Copyright (C) 2006 Free Software Foundation, Inc.]

a,b,c,d : give 0x8002 in both cases.

e,f give 0 (!) in the first case and 0x8002 in the 2nd cases

??

"When a finite value of real floating type is converted to an integer
type other than _Bool, the fractional part is discarded (i.e., the value
is truncated toward zero)" (6.3.1.4p1), so -32766.5 is converted to
-32766. That section goes on to say that "If the value of
the integral part cannot be represented by the integer type, the
behavior is undefined." Since -32766 cannot be represented in any
unsigned type, all of the results you've gotten are equally conforming.
A conforming implementation could also have formatted your hard disk or
sent pornographic e-mail to your boss, though those are far less likely
to occur.
Note : when i cast to a SHORT instead of an unsigned short in the first
case, ALL compilers give 0x8002

That's because short can can represent -32766. There is still a
conversion to unsigned short, which can't represent that value; but for
conversions from signed integer types to unsigned integer types, the
rules are different than for floating point types. If a value cannot be
represented in the new type, "the value is converted by repeatedly
adding or subtracting one more than the maximum value that can be
represented in the new type until the value is in the range of the new
type." (6.3.1.3p2). In this case, that means adding or subtracting one
more than USHORT_MAX, which is commonly 65536 (though it could be
larger). 65536-32766 == 0x8002.
 
Q

Quentin Pope

Yes. The first one is that the range for unsigned short is zero to
USHORT_MAX. Your program has undefined behavior since a negative value
will not go into an unsigned short, it is OUTSIDE its domain.

Sorry, but this is nonsense. Negative numbers stored in unsigned integer
types "wrap around" - there is NO overflow for unsigned types, but all
arithmetic is done modulo USHORT_MAX+1. It is amazing that you are not
aware of this as a compiler writer!
 
J

jacob navia

Le 02/12/11 23:36, Quentin Pope a écrit :
Sorry, but this is nonsense. Negative numbers stored in unsigned integer
types "wrap around" - there is NO overflow for unsigned types, but all
arithmetic is done modulo USHORT_MAX+1. It is amazing that you are not
aware of this as a compiler writer!


The C standard specifies that when the

<quote> (C Standard 6.3.1.4)
If the value being converted is outside the range of values that can
be represented, the behavior is undefined.
<end quote>

A negative value can't be represented in an UNsigned integer.

By definition.

Therefore my compiler emits a warning and does its best (as all other
compilers do) and produces exactly the same result as most other
compilers do.

I can't understand how you come to "overflow". There is nowhere an
"overflow" and I did not use that word at all. It is just that
the value can't be represented in the destination object.

Try putting 53765 into an 8 bit char... or a complex number
into a float...
 
B

Ben Bacarisse

Quentin Pope said:
Sorry, but this is nonsense. Negative numbers stored in unsigned integer
types "wrap around" - there is NO overflow for unsigned types, but all
arithmetic is done modulo USHORT_MAX+1. It is amazing that you are not
aware of this as a compiler writer!

It most certainly is not nonsense. I would have put it differently, but
it is a more accurate summary /of the code in question/ than your
remarks. You cut that context, which was of a conversion from float to
unsigned short. This conversion in *not* done modulo USHRT_MAX+1. To
be more accurate, it need not be done that way -- some implementations
may choose to do so since the result is undefined when the modulo
operation would kick in.

Jacob's "Your program has undefined behavior since a negative value will
not go into an unsigned short" is quite correct (assuming a 16-bit
unsigned short as everyone has been doing so far).
 
J

James Kuyper

jacob navia ha scritto: ....
The C standard specifies that when the

<quote> (C Standard 6.3.1.4)
If the value being converted is outside the range of values that can be
represented, the behavior is undefined.
<end quote>

The text you quote is 6.3.1.4 *Real floating and integer*

p2:
When _a value of integer type is converted to a real floating type_,
[...]
If the value being converted is outside the range of values that
can be represented, the behavior is undefined.

But now we are dealing with a real floating type being converted to
integer types, not the contrary!

His conclusion was correct, and he cited the right section of the
standard, but his quotation is from the wrong paragraph in that section.
What he should have cited was 6.3.1.4p1, which does cover conversion of
a real floating type to an integer: "If the value of the integral part
cannot be represented by the integer type, the behavior is undefined."
 
Q

Quentin Pope

Il 03/12/2011 17:51, James Kuyper ha scritto:

Yes, of course. That's what I wanted to point out indeed: the right
context in the Standard. I do believe that Jacob intended the right
thing, but he expressed it in the form of a very general rule about
conversion from "negative value"s to unsigned types that will eventually
lead to undefined behavior. He said:

"Your program has undefined behavior since a negative value will not go
into an unsigned short, it is OUTSIDE its domain. "

and

"<quote> (C Standard 6.3.1.4)
If the value being converted is outside the range of values that can
be represented, the behavior is undefined.
<end quote>

A negative value can't be represented in an UNsigned integer. "

One who didn't read the Standard might have been convinced of the
general rule for which a conversion of *any* type of negative value to
an unsigned type invokes UB. This is not true (even if the context looks
clear to most, but it may not be so to everyone). This is the reason of
my replies. :)

Yes! This is exactly the point I was making. The clear implication of
Jacob's words is that he was referring generally to all conversions of
numeric types to unsigned short, not just to floating point types.
 
K

Kaz Kylheku

Yes! This is exactly the point I was making.

It's perfectly clear to everyone you were making a fucking ass of yourself.

You should apologize to Navia.
 
P

Phil Carmody

Quentin Pope said:
Yes! This is exactly the point I was making. The clear implication of
Jacob's words is that he was referring generally to all conversions of
numeric types to unsigned short, not just to floating point types.

From the look of the two lines of C he was commenting on,
it looks like he's only refering to conversion of short to
unsigned short only:

:> Note : when i cast to a SHORT instead of an unsigned short in the first
:> case, ALL compilers give 0x8002
:> (cast to float to short to unsigned short)
:>
:> unsigned short s=(short)((float)(-32766.5));
:> or
:> unsigned short s=(unsigned short)(short)((float)(-32766.5));

Phil
 
J

James Kuyper

From the look of the two lines of C he was commenting on,
it looks like he's only refering to conversion of short to
unsigned short only:

:> Note : when i cast to a SHORT instead of an unsigned short in the first
:> case, ALL compilers give 0x8002
:> (cast to float to short to unsigned short)
:>
:> unsigned short s=(short)((float)(-32766.5));
:> or
:> unsigned short s=(unsigned short)(short)((float)(-32766.5));

I didn't see jacob's message, but the OP was asking primarily about
double->float->unsigned short, and was asking about
double->float->short->unsigned short only for the purpose of wondering
why it gave different results.

It suspect that double->float was part of the conversion chain only
because the OP was not aware of the fact that you can write float
constants directly, as -32766.5F.
 
M

Michael Press

Vincenzo Mercuri said:
p1:
When a finite value of real floating type is converted to an
integer type other than _Bool, the fractional part is discarded
(i.e., the value is truncated toward zero). If the value of the
integral part cannot be represented by the integer type,
the behavior is undefined.[^50]

Note that this wording is at variance with standard mathematcal definitions.

The floor function is defined as

floor(x) = maximum integer m such that m <= x.

Hence floor(x) <= x.

The fractional part of x is defined to be

frac(x) = x - floor(x).

Hence frac(x) >= 0.

By the C standard's implied definition the fractional
part of x is less than or equal to zero for x <= 0.
 
B

Ben Pfaff

Michael Press said:
Vincenzo Mercuri said:
p1:
When a finite value of real floating type is converted to an
integer type other than _Bool, the fractional part is discarded
(i.e., the value is truncated toward zero). If the value of the
integral part cannot be represented by the integer type,
the behavior is undefined.[^50]

Note that this wording is at variance with standard mathematcal definitions.

If http://mathworld.wolfram.com/FractionalPart.html is to be
believed, there is no single standard mathematical definition of
"fractional part", but the one used in the C standard matches one
common definition.
 
K

Keith Thompson

Michael Press said:
Vincenzo Mercuri said:
p1:
When a finite value of real floating type is converted to an
integer type other than _Bool, the fractional part is discarded
(i.e., the value is truncated toward zero). If the value of the
integral part cannot be represented by the integer type,
the behavior is undefined.[^50]

Note that this wording is at variance with standard mathematcal definitions.

The floor function is defined as

floor(x) = maximum integer m such that m <= x.

Hence floor(x) <= x.

Yes, and that's consistent with the C standard's floor(), floorf(),
and floorl() functions in said:
The fractional part of x is defined to be

frac(x) = x - floor(x).

Hence frac(x) >= 0.

Can you cite a source that says that that's what "fractional part"
means in mathematics?
By the C standard's implied definition the fractional
part of x is less than or equal to zero for x <= 0.

Yes.
 
N

Nobody

By the C standard's implied definition the fractional
part of x is less than or equal to zero for x <= 0.

I read it as treating a floating-point value as:

sign * (integer_part + fractional_part)

where both integer_part and fractional_part are non-negative. Converting
to an integer discards fractional_part.
 
M

Michael Press

Keith Thompson said:
Michael Press said:
Vincenzo Mercuri said:
p1:
When a finite value of real floating type is converted to an
integer type other than _Bool, the fractional part is discarded
(i.e., the value is truncated toward zero). If the value of the
integral part cannot be represented by the integer type,
the behavior is undefined.[^50]

Note that this wording is at variance with standard mathematcal definitions.

The floor function is defined as

floor(x) = maximum integer m such that m <= x.

Hence floor(x) <= x.

Yes, and that's consistent with the C standard's floor(), floorf(),
and floorl() functions in said:
The fractional part of x is defined to be

frac(x) = x - floor(x).

Hence frac(x) >= 0.

Can you cite a source that says that that's what "fractional part"
means in mathematics?

Yes. Why? Do you have a source that states otherwise?




















































































































Knuth, ACP, 1.2.4.

Oxford Dictionary of Mathematics
<http://books.google.com/books?id=UT...ia_b9uW&sig=Tojsd5nB2_gcZixDfGfB8SRVjAo&hl=en>
 
J

James Kuyper

Yes. Why? Do you have a source that states otherwise?

At the time Keith posted, Ben Pfaff had already given a URL for a
Mathematica web site indicating that "Spanier and Oldham (1987) use the
same definition as Mathematica", which is (probably not coincidentally)
the same as C's definition.

....
[snip 116 blank lines]
What was the purpose of those blank lines?
 
M

Michael Press

James Kuyper said:
Yes. Why? Do you have a source that states otherwise?

At the time Keith posted, Ben Pfaff had already given a URL for a
Mathematica web site indicating that "Spanier and Oldham (1987) use the
same definition as Mathematica", which is (probably not coincidentally)
the same as C's definition.

...
[snip 116 blank lines]
What was the purpose of those blank lines?

I will wait until Keith asks.
 
M

Michael Press

Nobody said:
I read it as treating a floating-point value as:

sign * (integer_part + fractional_part)

where both integer_part and fractional_part are non-negative. Converting
to an integer discards fractional_part.

What is your point here?
What definition of fractional part does your reading imply?
 
K

Keith Thompson

Michael Press said:
Hence frac(x) >= 0.

Can you cite a source that says that that's what "fractional part"
means in mathematics?

Yes. Why? Do you have a source that states otherwise?

At the time Keith posted, Ben Pfaff had already given a URL for a
Mathematica web site indicating that "Spanier and Oldham (1987) use the
same definition as Mathematica", which is (probably not coincidentally)
the same as C's definition.

...
[snip 116 blank lines]
What was the purpose of those blank lines?

I will wait until Keith asks.

Ok, what was the purpose of those blank lines? And why would you feel
the need to wait until I ask about it?

When I read your response, I didn't even realize that those blank lines
were there. I went to the next article thinking that you had said that
you have a source but weren't going to share it (and was about to remark
on that.

My working hypothesis is that you were being deliberately difficult.

Ok. My point is that "mathematics" is a very large field, and I'm
skeptical that there's a single definition for a term like "fractional
part" that all mathematicians would accept.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top