Strange constant behavior - why?
Author Message Strange constant behavior - why?

I am using a constant to define a page height to width ratio, and I'm
getting a very strange result in one case. Can anyone explain this?

// for letter-size pages, returns 1.294
const float PageRatio = (float)(11 / 8.5);

// for A4-size pages, returns 1.414
const float PageRatio = (float)(29.7 / 21);

// My original construction for A4-size pages... returns 1!
const float PageRatio = (float)(297 / 210);

The first two work fine, the third one assigns a value of 1. Since
29.7/21 (centimeters) is the same as 297/210 (millimeters), shouldn't
both of these work? Is this a bug or some subtlety I've missed?

--

|           James Gifford - Nitrosyncretic Press            |
| http://www.*-*-*.com/ for the Heinlein FAQ & more |

Sat, 28 May 2005 14:01:29 GMT  Strange constant behavior - why?

Quote:
> const float PageRatio = (float)(297 / 210);

I am thinking that the compiler saw (297 / 210) as being integer
arithmetic - the answer to which is 1.  Which is then cast to a float, for

Presumably...
(float) (297.0 / 210.0)
would give you an answer closer to what you were expecting.

--Don

--
This posting is provided "AS IS" with no warranties, and confers no rights.

Quote:
> I am using a constant to define a page height to width ratio, and I'm
> getting a very strange result in one case. Can anyone explain this?

> // for letter-size pages, returns 1.294
> const float PageRatio = (float)(11 / 8.5);

> // for A4-size pages, returns 1.414
> const float PageRatio = (float)(29.7 / 21);

> // My original construction for A4-size pages... returns 1!
> const float PageRatio = (float)(297 / 210);

> The first two work fine, the third one assigns a value of 1. Since
> 29.7/21 (centimeters) is the same as 297/210 (millimeters), shouldn't
> both of these work? Is this a bug or some subtlety I've missed?

> --

> |           James Gifford - Nitrosyncretic Press            |
> | http://www.nitrosyncretic.com for the Heinlein FAQ & more |

Sat, 28 May 2005 14:33:21 GMT  Strange constant behavior - why?

Quote:

>> const float PageRatio = (float)(297 / 210);
> I am thinking that the compiler saw (297 / 210) as being integer
> arithmetic - the answer to which is 1.  Which is then cast to a float, for

> Presumably...
>     (float) (297.0 / 210.0)
> would give you an answer closer to what you were expecting.

Bingo. How weird... but makes sense in retrospect. But then, everyone
has 20.0-20.0 hindsight. :)

Thanks.

--

|           James Gifford - Nitrosyncretic Press            |
| http://www.nitrosyncretic.com for the Heinlein FAQ & more |

Sat, 28 May 2005 14:39:47 GMT  Strange constant behavior - why?

Quote:
> I am using a constant to define a page height to width ratio,
> and I'm getting a very strange result in one case. Can anyone
> explain this?

> // for letter-size pages, returns 1.294
> const float PageRatio = (float)(11 / 8.5);

> // for A4-size pages, returns 1.414
> const float PageRatio = (float)(29.7 / 21);

> // My original construction for A4-size pages... returns 1!
> const float PageRatio = (float)(297 / 210);

> The first two work fine, the third one assigns a value of 1.
> Since 29.7/21 (centimeters) is the same as 297/210
> (millimeters), shouldn't both of these work? Is this a bug or
> some subtlety I've missed?

James,

Adding a "point zero" to one (or both) numbers will work.

const float PageRatio = (float)(297.0 / 210); // and/or 210.0

C# does the division first, then the assigment.  With the
expression 297/210, both numbers are integers, so C# does integer
division, resulting in an answer of 1.

Adding a ".0" to one (or both) numbers will tell C# to do floating
point division, resulting in the correct answer of 1.414286.

Hope this helps.

Chris.
-------------
C.R. Timmons Consulting, Inc.
http://www.crtimmonsinc.com/

Sat, 28 May 2005 14:41:10 GMT  Strange constant behavior - why?
it's nothing magic or arbitrarily..

There a couple of predefined operators, these are:

for integer division:

int operator /(int x, int y);
uint operator /(uint x, uint y);
long operator /(long x, long y);
ulong operator /(ulong x, ulong y);

for floating point division:

float operator /(float x, float y);
double operator /(double x, double y);

and for decimal division:

decimal operator /(decimal x, decimal y);

now, quite frankly, when the compiler detects a division in code, it somehow
has to decide which one it takes to perform the division.
The exact algorithm is pretty complicated and is explained in the C#
language reference  at Section 7.4.2

if we simplify it, it comes down to

1) if there is an exactly fitting operator, take that.
2) if thats not possible take the one that requires the least amount of
implicit conversion

if it's not possible to find a match with implicit conversions there is no
match possible, and a compile time error will occur.

implicit conversions are conversion that do not lose any information, and
thus can be performed automatically by the compiler, examples are

int -> long
int -> float
float -> double
int -> double

now, if you have 29.7 / 21 the following happens:

there is no division operator that takes a float and a int, so the compilers
needs to convert one of the values..

you can't implicitly convert from float -> int, but you can convert from
int -> float, so the compiler uses the float division operator, which
returns a float value

if you have 297 / 210 it will use the integer division operator, so the
result will be an int, hence the wrong result..

now, as mentioned you can add .0 behind every number so it's an float for
sure, but there is a more precise way

In C# there are numeric suffixes defined

1L    for 1 in long (can be mixed case, so 1l is allowed as well);
1UL for 1 in unsigned long (can be mixed case and other orde, so 1lu is
allowed as well)
1f     for 1.0 in float
1d    for 1.0 in double
1m   for 1,00 in decimal

a integer number without suffix will be treated as an int unless the number
doesn't fit in 32 bits
a floating point number without suffix will be treated as an single (I dont
know what happens when the precision is better in double, since that is
usually the case)

damn, i'm long winded :-(

Ah well, really off to bed now..

Willem

Quote:
> I am using a constant to define a page height to width ratio, and I'm
> getting a very strange result in one case. Can anyone explain this?

> // for letter-size pages, returns 1.294
> const float PageRatio = (float)(11 / 8.5);

> // for A4-size pages, returns 1.414
> const float PageRatio = (float)(29.7 / 21);

> // My original construction for A4-size pages... returns 1!
> const float PageRatio = (float)(297 / 210);

> The first two work fine, the third one assigns a value of 1. Since
> 29.7/21 (centimeters) is the same as 297/210 (millimeters), shouldn't
> both of these work? Is this a bug or some subtlety I've missed?

> --

> |           James Gifford - Nitrosyncretic Press            |
> | http://www.nitrosyncretic.com for the Heinlein FAQ & more |

Sun, 29 May 2005 09:49:17 GMT

 Page 1 of 1 [ 5 post ]

Relevant Pages