473,385 Members | 2,162 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,385 software developers and data experts.

Rounding Problem

I am having a rounding problem in a value i am trying to display in VB.NET.

If I have the following code:
Dim x As Single = 2726.795
Dim y As Single = Math.Round(2726.795, 2)
Dim s as String = String.Format("{0:0.00}", y)
The value of s is 2726.79

If I have the following code:
Dim y As Single = Math.Round(2726.795, 2)
Dim s as String = String.Format("{0:0.00}", y)
The value of s is 2726.80

I need to use the first example as I read the value of x in as a string from
an xml file then convert it to a single in order to round and format it to 2
decimal places for a report display.

Any ideas why the first example is not rounding to 2726.80?

May 30 '06 #1
5 2236
[the short answer is at the end]

Jason wrote:
I am having a rounding problem in a value i am trying to display in VB.NET.

If I have the following code:
Dim x As Single = 2726.795
Dim y As Single = Math.Round(2726.795, 2)
Dim s as String = String.Format("{0:0.00}", y)
The value of s is 2726.79

If I have the following code:
Dim y As Single = Math.Round(2726.795, 2)
Dim s as String = String.Format("{0:0.00}", y)
The value of s is 2726.80
The two lines of the second example are the same as the second two
lines of the first example. I suspect you have a typo somewhere.

Incidentally, I see you are running without the benefit of Option
Strict (Math.Round returns a Double which cannot be implicitly
converted to a Single). I suggest turning it on - the additional code
sometimes required is a small price to pay for the increased
compile-time checking.
My guess is that you meant the first example to be:

Dim x As Single = 2726.795
Dim y As Single = Math.Round(x, 2)
Dim s As String = String.Format("{0:0.00}", y)

which *does* produce 2726.795.

Assuming that is the right correction:
Any ideas why the first example is not rounding to 2726.80?
The first parameter to the particular overload of Math.Round being used
is a Double. That means that when a Single is supplied (as in the
corrected first example), it must be converted to a Double. This is OK
to be done implicitly, since it is a widening conversion. Let's have a
look at the actual exact values involved:

Dim x As Single = 2726.795
Dim xAsDouble As Double = x

Console.WriteLine(x.ToString("G9"))
Console.WriteLine(xAsDouble.ToString("R"))

The output is

2726.79492
2726.794921875

So we see that trying to put 2726.795 into a Single actually puts in a
value slightly *less* than 2726.795, which is why it gets rounded to
....79. With a double, on the other hand (as in the second example):

Dim x As Double = 2726.795

Console.WriteLine(x.ToString("G17"))

2726.7950000000001

So trying to put 2726.295 into a Double actually puts in a value
slightly *more* than 2726.295, which is why it gets rounded to ...80.
That's the why. The next question is the what-to-do.

I'd say the first recommendation is this: don't use floating-point
types to deal with exact values. Actually it's more than a
recommendation, it's a golden rule. It's customary for me to give my
usual example at this point:

Debug.Print(0.1+0.1+0.1-0.3) 'guess output before running!
The next recommendation would be, don't use Single at all unless you
have a very good reason. Single only has about *seven* decimal digits
of precision, which we run into pretty quickly in the real world. Any
memory gains you think you might be getting by using Singles over
Doubles are almost certainly illusory. Any performance gains you think
you are getting are _wrong_: "Double is the most efficient of the
fractional data types, because the processors on current platforms
perform floating-point operations in double precision", to quote the
docs. In short, if you are going to use floating point (with the above
caveat that you shouldn't if... you shouldn't), use Double not Single.

And now for the short answer:
I need to use the first example as I read the value of x in as a string from
an xml file then convert it to a single in order to round and format it to 2
decimal places for a report display.


Use Decimal as the intermediate data type to avoid loss of precision.

--
Larry Lard
Replies to group please

May 30 '06 #2
Larry,

Using Decimal cuts right to the chase:

Dim myDec As Decimal = 2726.795

MsgBox(Math.Round(myDec, 2))

This code produces 2726.80, which the OP does not want.

Of course, the reason that Math.Round produces this value is very clearly
laid out in the docs on Math.Round (IEEE Standard 754, section 4 or banker's
rounding).

The real question is probably "How to do rounding that rounds 2726.795 to
2726.79.

Maybe using INT or FIX or FLOOR, etc is the required approach.

Kerry Moorman

"Larry Lard" wrote:

Use Decimal as the intermediate data type to avoid loss of precision.


May 30 '06 #3
> Larry,

Using Decimal cuts right to the chase:

Dim myDec As Decimal = 2726.795

MsgBox(Math.Round(myDec, 2))

This code produces 2726.80, which the OP does not want.

Of course, the reason that Math.Round produces this value is very
clearly laid out in the docs on Math.Round (IEEE Standard 754, section
4 or banker's rounding).

The real question is probably "How to do rounding that rounds 2726.795
to 2726.79.

Maybe using INT or FIX or FLOOR, etc is the required approach.


Round includes an additional overloaded version which allows you to specify
the rounding method you want: banker's round or away from 0 rounding. Unfortunately
the framework isn't necessarily consistant in rounding approaches. Math.Round
uses bankers rounding by default, but Format and ToString(c2) use away from
0 rounding. See my write-up at http://devauthority.com/blogs/jwoole...03/24/806.aspx
for more.

Jim Wooley
http://devauthority.com/blogs/jwooley/default.aspx
May 30 '06 #4
Jim

That information, about MidpointRounding.AwayFromZero, is good to know and
may go a ways to help clear up the confusion that has always surrounded the
Math.Round method. I had not seen that before you pointed it out.

Unfortunately, its a .Net 2.0-only feature.

Kerry Moorman
"Jim Wooley" wrote:

Round includes an additional overloaded version which allows you to specify
the rounding method you want: banker's round or away from 0 rounding. Unfortunately
the framework isn't necessarily consistant in rounding approaches. Math.Round
uses bankers rounding by default, but Format and ToString(c2) use away from
0 rounding. See my write-up at http://devauthority.com/blogs/jwoole...03/24/806.aspx
for more.

Jim Wooley
http://devauthority.com/blogs/jwooley/default.aspx

May 30 '06 #5
Cheers for the reply.

I will switch from using Single to Double as that has solved my problem. The
reason I have been using Single is that was the type I get back from my
DataSet schema when connecting to the Access database I am working with. I
will explicitly convert to Double in code for rounding functions.

"Larry Lard" wrote:
[the short answer is at the end]

Jason wrote:
I am having a rounding problem in a value i am trying to display in VB.NET.

If I have the following code:
Dim x As Single = 2726.795
Dim y As Single = Math.Round(2726.795, 2)
Dim s as String = String.Format("{0:0.00}", y)
The value of s is 2726.79

If I have the following code:
Dim y As Single = Math.Round(2726.795, 2)
Dim s as String = String.Format("{0:0.00}", y)
The value of s is 2726.80


The two lines of the second example are the same as the second two
lines of the first example. I suspect you have a typo somewhere.

Incidentally, I see you are running without the benefit of Option
Strict (Math.Round returns a Double which cannot be implicitly
converted to a Single). I suggest turning it on - the additional code
sometimes required is a small price to pay for the increased
compile-time checking.
My guess is that you meant the first example to be:

Dim x As Single = 2726.795
Dim y As Single = Math.Round(x, 2)
Dim s As String = String.Format("{0:0.00}", y)

which *does* produce 2726.795.

Assuming that is the right correction:
Any ideas why the first example is not rounding to 2726.80?


The first parameter to the particular overload of Math.Round being used
is a Double. That means that when a Single is supplied (as in the
corrected first example), it must be converted to a Double. This is OK
to be done implicitly, since it is a widening conversion. Let's have a
look at the actual exact values involved:

Dim x As Single = 2726.795
Dim xAsDouble As Double = x

Console.WriteLine(x.ToString("G9"))
Console.WriteLine(xAsDouble.ToString("R"))

The output is

2726.79492
2726.794921875

So we see that trying to put 2726.795 into a Single actually puts in a
value slightly *less* than 2726.795, which is why it gets rounded to
....79. With a double, on the other hand (as in the second example):

Dim x As Double = 2726.795

Console.WriteLine(x.ToString("G17"))

2726.7950000000001

So trying to put 2726.295 into a Double actually puts in a value
slightly *more* than 2726.295, which is why it gets rounded to ...80.
That's the why. The next question is the what-to-do.

I'd say the first recommendation is this: don't use floating-point
types to deal with exact values. Actually it's more than a
recommendation, it's a golden rule. It's customary for me to give my
usual example at this point:

Debug.Print(0.1+0.1+0.1-0.3) 'guess output before running!
The next recommendation would be, don't use Single at all unless you
have a very good reason. Single only has about *seven* decimal digits
of precision, which we run into pretty quickly in the real world. Any
memory gains you think you might be getting by using Singles over
Doubles are almost certainly illusory. Any performance gains you think
you are getting are _wrong_: "Double is the most efficient of the
fractional data types, because the processors on current platforms
perform floating-point operations in double precision", to quote the
docs. In short, if you are going to use floating point (with the above
caveat that you shouldn't if... you shouldn't), use Double not Single.

And now for the short answer:
I need to use the first example as I read the value of x in as a string from
an xml file then convert it to a single in order to round and format it to 2
decimal places for a report display.


Use Decimal as the intermediate data type to avoid loss of precision.

--
Larry Lard
Replies to group please

May 31 '06 #6

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

Similar topics

3
by: Caesar Augustus | last post by:
Hello Tom, Long time listener, first time caller... I have been working with vb code to automate a salary increase process that not only rounds to the nearest penny but also rounds to the...
0
by: Rick Gabel | last post by:
Trying to use the decimal datatype with SQL Server2000 and C#.Net and having a rounding problem. I am using SqlCommand/SqlParameter process to retrieve and insert a record into the table. One...
11
by: cj | last post by:
Lets assume all calculations are done with decimal data types so things are as precise as possible. When it comes to the final rounding to cut a check to pay dividends for example in VB rounding...
4
by: Altman | last post by:
I am having a rounding problem all over the place and am struggling to fix it. My problem is that I have an unit price and a quantity. When I multiply them together they come out to 3.705. I...
29
by: Marco | last post by:
Hello, I have : float f = 36.09999999; When I do : char cf; sprintf(cf,"%0.03lf", f); I get : 36.100
18
by: jdrott1 | last post by:
i'm trying to round my currency string to end in 9. it's for a pricing application. this is the function i'm using to get the item in currency: FormatCurrency(BoxCost, , , , TriState.True) if...
206
by: md | last post by:
Hi Does any body know, how to round a double value with a specific number of digits after the decimal points? A function like this: RoundMyDouble (double &value, short numberOfPrecisions) ...
20
by: jacob navia | last post by:
Hi "How can I round a number to x decimal places" ? This question keeps appearing. I would propose the following solution #include <float.h> #include <math.h>
30
by: bdsatish | last post by:
The built-in function round( ) will always "round up", that is 1.5 is rounded to 2.0 and 2.5 is rounded to 3.0. If I want to round to the nearest even, that is my_round(1.5) = 2 # As...
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: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
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
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
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
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
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

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.