473,399 Members | 4,254 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,399 software developers and data experts.

simple casting problem (with small code example)


Can someone explain this:

void Test()
{
short x = 10;
float y = 9.9f;

float a = (float)x;
a *= y;
short b = (short)a; // I get 99. Good!

short c = (short)(((float)x) * y); // I get 98. Not so
good.
}

In both cases my logic is to cast the short to float, do floating
multiplication, and cast the result to short.

Why do I get different results?
Buzz

May 11 '07 #1
8 1405
>In both cases my logic is to cast the short to float, do floating
>multiplication, and cast the result to short.

Why do I get different results?
I assume you're running on .NET Framework 1.x. Under 2.0 I get 98 in
both cases, which actually is correct even if it's not what you
expect.

The root cause is that not all numbers can be stored exactly when
using floating point representation. Read more here
http://www.yoda.arachsys.com/csharp/floatingpoint.html

In this case, 9.9 is stored as something closer to 9.899.....

Casting the result back to short discards the decimals without any
rounding, so the result becomes 98.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
May 11 '07 #2
I assume you're running on .NET Framework 1.x. Under 2.0 I get 98 in
both cases, which actually is correct even if it's not what you
expect.
Actually I am using 2.0.50727, and I have 3.0 installed. But my
understanding is 3.0 is just additional libraries... same runtime as
2.0.

I simply created a windows application project in VS 2005, and I'm
looking at the values in the debugger by dragging over them.

Should I be using the System.Convert routines? Some of what I am
doing involves large data cubes and I am concerned about performance.

Buzz

May 11 '07 #3
>Actually I am using 2.0.50727, and I have 3.0 installed. But my
>understanding is 3.0 is just additional libraries... same runtime as
2.0.

I simply created a windows application project in VS 2005, and I'm
looking at the values in the debugger by dragging over them.
Right, I see the same behavior now even on 2.0. Seems to be one of
those cases where release/debug (or rather optimized or not) code gen
gives different result.

>Should I be using the System.Convert routines? Some of what I am
doing involves large data cubes and I am concerned about performance.
I guess that depends on what you want to accomplish. If you want to
round the result to the nearest integer you can try using Math.Round.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
May 11 '07 #4
I don't think that the Round method is appropriate here. While
performance is a concern, it seems that the OP really has a need for
accuracy when using floating point numbers. To that end, the OP should be
using the decimal type, and not a float:

short x = 10;
decimal y = 9.9M;

decimal a = x;
a *= y;
short b = (short) a; // I get 99. Good!

short c = (short) (x * y);

This will populate c with 99, as expected.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Mattias Sjögren" <ma********************@mvps.orgwrote in message
news:eS**************@TK2MSFTNGP04.phx.gbl...
Actually I am using 2.0.50727, and I have 3.0 installed. But my
understanding is 3.0 is just additional libraries... same runtime as
2.0.

I simply created a windows application project in VS 2005, and I'm
looking at the values in the debugger by dragging over them.

Right, I see the same behavior now even on 2.0. Seems to be one of
those cases where release/debug (or rather optimized or not) code gen
gives different result.

>>Should I be using the System.Convert routines? Some of what I am
doing involves large data cubes and I am concerned about performance.

I guess that depends on what you want to accomplish. If you want to
round the result to the nearest integer you can try using Math.Round.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

May 12 '07 #5
On May 11, 12:15 pm, buzzweet...@gmail.com wrote:
Can someone explain this:

void Test()
{
short x = 10;
float y = 9.9f;

float a = (float)x;
a *= y;
short b = (short)a; // I get 99. Good!

short c = (short)(((float)x) * y); // I get 98. Not so
good.
}

In both cases my logic is to cast the short to float, do floating
multiplication, and cast the result to short.

Why do I get different results?
Buzz
When you set a to the result of (float)x the CLR takes it's higher
precision floating point representation and casts it to the float
type, it seems this makes it 10 so that 9.9 * 10 = 99. In the second
part you never get the CLR a chance to cast back, so it takes it's
internal representation of (float)x (which must be something similar
to 9.999999999998) and mutilplies it to y so that 9.9 *
9.9999999999998 = 98.

We can examine the IL and see what's going on:
[0] int16 x,
[1] float32 y,
[2] float32 a,
[3] int16 b,
[4] int16 c

nop
ldc.i4.s 10
stloc.0

[short x = 10]

ldc.r4 9.9
stloc.1

[float y = 9.9]

ldloc.0
conv.r4
stloc.2 <-- Here's the implict cast

[float a = (float)x]

ldloc.2
ldloc.1
mul
stloc.2

[a = a * y] or [a = 10 * 9.9 or 99]

ldloc.2
conv.i2
stloc.3

[b = (int)a]

ldloc.0
conv.r4
ldloc.1 <-- no storing of the variable, in the next command we
multiple the resolve of the conv.4 with y
mul
conv.i2
stloc.s c

[c = (short)((float)x * y) or [ c = (short) (9.999999999998 * 9.9) or
98]
some nitty gritty if you're interested:
http://blogs.msdn.com/davidnotario/a...08/449092.aspx

You may also want to see http://msdn2.microsoft.com/en-us/lib...75(VS.80).aspx

May 12 '07 #6
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard.caspershouse.comwrote:
I don't think that the Round method is appropriate here. While
performance is a concern, it seems that the OP really has a need for
accuracy when using floating point numbers. To that end, the OP should be
using the decimal type, and not a float:
.... so long as he bears in mind that "accurate" here just means "able
to store decimal numbers to 28 places accurately. It's not like
float/double are inherently inaccurate and decimal is inherently
accurate - they just use different bases.

Trying to represent 1/3 in decimal will lead to the same kind of
inaccuracy as using float or double to represent 0.1.

I know you're aware of this - I'm just questioning you're use of the
word "accuracy". Certainly people often infer that more is going on
than is actually the case.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
May 12 '07 #7
I would disagree slightly here.

Your two points are valid, but in this case, the inability of a
float/double type to faithfully represent a value with an exact
representation such as "0.99" (not the decimal representation of 1/3 which
is .33 with three repeating (can't do overbars)) to me comes across as
pretty inaccurate. =)
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP********************@msnews.microsoft.com.. .
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard.caspershouse.comwrote:
> I don't think that the Round method is appropriate here. While
performance is a concern, it seems that the OP really has a need for
accuracy when using floating point numbers. To that end, the OP should
be
using the decimal type, and not a float:

... so long as he bears in mind that "accurate" here just means "able
to store decimal numbers to 28 places accurately. It's not like
float/double are inherently inaccurate and decimal is inherently
accurate - they just use different bases.

Trying to represent 1/3 in decimal will lead to the same kind of
inaccuracy as using float or double to represent 0.1.

I know you're aware of this - I'm just questioning you're use of the
word "accuracy". Certainly people often infer that more is going on
than is actually the case.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

May 12 '07 #8
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard.caspershouse.comwrote:
I would disagree slightly here.

Your two points are valid, but in this case, the inability of a
float/double type to faithfully represent a value with an exact
representation such as "0.99" (not the decimal representation of 1/3 which
is .33 with three repeating (can't do overbars)) to me comes across as
pretty inaccurate. =)
1/3 is only recurring in base 10. It's not in base 3 - in base 3, the
representation is just 0.1. Decimal's failure to represent 0.1 base 3
is exactly the same as float/double's failure to represent 0.1 base 10.
The OP happens to want to represent 0.99 (value) so for that
*particular* value decimal is exact and float/double aren't, but that
doesn't make it true of the types in general. Would the decimal type
*as a whole* become inaccurate if the OP had wanted to represent 1/3?

There's nothing particularly magical about base 10, it's just what
humans happen to usually use to write down numbers. Maths itself
doesn't care.

Saying that decimal is accurate and float/double are inaccurate
suggests there's a big difference in what they do - there isn't.
They're all floating point types (admittedly with significant
differences in choice of available mantissa/exponent sizes) it's just
that decimal uses a floating *decimal* point and float/double use a
floating *binary* point.

Saying decimal is accurate and float/double sometimes inaccurate for
values which are exactly representable in a decimal form is correct
(although I'd use the word exact rather than accurate) - saying decimal
is accurate as a blanket statement is dodgier, IMO.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
May 12 '07 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

35
by: ytrama | last post by:
Hi, I have read in one of old posting that don't cast of pointer which is returned by the malloc. I would like to know the reason. Thanks in advance, YTR
6
by: Justin | last post by:
I am trying to add dollar amounts together and add sales tax but everthing after the decimal point is being cut off in the dollar amounts. Here is my code: if (Adults != "") { AdultTotal =...
8
by: wkaras | last post by:
In my compiler, the following code generates an error: union U { int i; double d; }; U u; int *ip = &u.i; U *up = static_cast<U *>(ip); // error I have to change the cast to...
13
by: DaTurk | last post by:
Hi, This is a question brought about by a solution I came up with to another question I had, which was "Dynamic object creation". So, I'm curious if you can dynamically cast an object. If you...
13
by: aum | last post by:
Hi, I'm a Python programmer, just starting to get into javascript. On reading some of the js guides, and not liking any of the OO usage patterns I saw, I've cooked up something which python...
7
by: S. Lorétan | last post by:
Hi guys, Sorry for this stupid question, but I don't know why it isn't working. Here is my (example) code: namespace Test { class A { public string Label1; }
17
by: sophia.agnes | last post by:
Hi , I was going through peter van der linden's book Expert C programming, in this book there is a section named "How and why to cast" the author then says as follows (float) 3 - it's a...
32
by: alex.j.k2 | last post by:
Hello all, I have "PRECISION" defined in the preprocessor code and it could be int, float or double, but I do not know in the code what it is. Now if I want to assign zero to a "PRECISION"...
19
by: =?Utf-8?B?WWFua2VlIEltcGVyaWFsaXN0IERvZw==?= | last post by:
I'm doing my c# more and more like i used to code c++, meaning i'm casting more often than creating an instance of objects. like : protected void gvOrderDetailsRowDataBound(object sender,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.