rounding to 9's

  • Thread starter Thread starter jdrott1
  • Start date Start date
J

jdrott1

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 an item is 41.87 i want the application to bring it up to 41.89

if an item is 41.84 i want the application to round down to 41.79

does anyone know how i could do this?
 
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 an item is 41.87 i want the application to bring it up to 41.89

if an item is 41.84 i want the application to round down to 41.79

does anyone know how i could do this?

You would have to do it manually - just parse the second digit after
the decimal and adjust the value accordingly.

Thanks,

Seth Rowe
 
Hi Jonathan -

Have you tried rounding to the nearest tenth and subtracting one
hundreth?

Dim myVal As Double
myVal = 41.87
myVal = Math.Round(myVal, 1) - 0.01
Debug.WriteLine(myVal) 'Returns 41.89

myVal = 41.84
myVal = Math.Round(myVal, 1) - 0.01
Debug.WriteLine(myVal) 'Returns 41.79

....sometimes the simplest approaches work the best.

Happy Coding,

-Mark
 
Hi Jonathan -

Have you tried rounding to the nearest tenth and subtracting one
hundreth?

Dim myVal As Double
myVal = 41.87
myVal = Math.Round(myVal, 1) - 0.01
Debug.WriteLine(myVal) 'Returns 41.89

myVal = 41.84
myVal = Math.Round(myVal, 1) - 0.01
Debug.WriteLine(myVal) 'Returns 41.79

...sometimes the simplest approaches work the best.

Happy Coding,

-Mark

i'll give it a try. thanks.
 
Hi Jonathan -

Have you tried rounding to the nearest tenth and subtracting one
hundreth?

Dim myVal As Double
myVal = 41.87
myVal = Math.Round(myVal, 1) - 0.01
Debug.WriteLine(myVal) 'Returns 41.89

myVal = 41.84
myVal = Math.Round(myVal, 1) - 0.01
Debug.WriteLine(myVal) 'Returns 41.79

...sometimes the simplest approaches work the best.

Happy Coding,

-Mark

(I haven't checked, but my initial impression is ...)

That would give you 5 results causing the value to
be rounded down, 4 results rounded up, and the last
(.x5) would go either way, so in total, you would have
more numbers being rounded down than up. Is that
really what you want for a pricing function?

Make sure that .x5 values are always rounded *up*
before subtracting the .01 in order to get an even split.

Regards,

Joergen Bech
 
Hi Joregen -

How are you getting 4 down and 5 up? Last time I checked, we were
using base ten.

Numbers ending in 0-4 are rounded down, 5-9 are rounded up; 5 on each
side.

Thanks,

-Mark
 
jdrott1 said:
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 an item is 41.87 i want the application to bring it up to 41.89

if an item is 41.84 i want the application to round down to 41.79

does anyone know how i could do this?

Set two decimal places correcting the error in the Int function for proper
mathematical rounding we have a very simple function:
X = Int(10*(X+0.005))/10

Now set one decimal place mathematical and subtract 1c:
X = Int(10 * (X + 0.06)) / 10 - 0.01
Here, 4 rounds up to 9 as per 5 rounding up to 10
& 3 rounds down to 9 as per 4 rounding down to 0
In the correct mathematical method:
IE +1 inside the brackets compensates -1 outside
just as *10 inside the brackets balances /10 outside.

THUS:

Public Function Nanofy(X as Double) as Double
Nanofy = Int(10 * (X + 0.06)) / 10 - 0.01
End Function

Executing:
Dim x=MsgBox("The Value is: $", CStr(Nanofy(CDble(InputBox(_
"Enter a Value","Enter a Value")))),MsgBoxStyle.OkOnly,"The answer is")

Nanofy(41.84) Returns 41.89
Nanofy(41.83) Returns 41.79


To bias rounding upwards,
simply increment the inner bracket sum in isolation.

SO:
Public Function Nanofy(X as Double) as Double
Nanofy = Int(10 * (X + 0.05)) / 10 - 0.01
End Function

Thus executing:
Dim x=MsgBox("The Value is: $", CStr(Nanofy(CDble(InputBox(_
"Enter a Value","Enter a Value")))),MsgBoxStyle.OkOnly,"The answer is")

Nanofy(41.85) Returns 41.89
Nanofy(41.84) Returns 41.79

Good luck...
 
"Number 11950 - GPEMC! Replace number with 11950" <[email protected]>
wrote in message

ERRATA:

[SNIP]
Set two decimal places correcting the error in the Int function for proper
mathematical rounding we have a very simple function:
X = Int(10*(X+0.005))/10
[SNIP]

This should read:

Set ONE decimal place correcting the error in the Int function for proper
mathematical rounding we have a very simple function:
X = Int(10*(X+0.005))/10

Cheers
 
Yeah, that was definately much easier than my solution.

So... In what instance would this give a different result than mine?

Apparently Blind,

-Mark
 
Hi Joregen -

How are you getting 4 down and 5 up? Last time I checked, we were
using base ten.

Numbers ending in 0-4 are rounded down, 5-9 are rounded up; 5 on each
side.

Thanks,

-Mark

I said 5 down, 4 up, and the last could go either way.

Because you are using simple Math.Round, which will round off 5s
to the nearest *even* value, e.g. 2.5 becomes 2, 3.5 becomes 4,
4.5 becomes 4, 5.5 becomes 6, and so on. That is great if that
is what you want, but I presumed it did not apply to the original
poster's needs.

Here is your suggestion wrapped in a test program:
---snip---
Private Sub RoundingTest()
Dim ups As Integer = 0
Dim downs As Integer = 0
Dim totalcount As Integer = 0
For value As Decimal = 1D To 1.99D Step 0.01D
Dim roundedvalue As Decimal = Math.Round(value, 1) - 0.01D
Debug.WriteLine(value.ToString("0.00") & ": " &
roundedvalue.ToString("0.00"))
totalcount = totalcount + 1
If roundedvalue < value Then
downs = downs + 1
Else
ups = ups + 1
End If
Next

Debug.WriteLine("------------------------")
Debug.WriteLine("Total: " & totalcount.ToString)
Debug.WriteLine("Ups: " & ups.ToString)
Debug.WriteLine("Downs: " & downs.ToString)

End Sub
---snip---

The results are below: 55 values rounded down, 45 rounded
up.

You can read about various rounding methods here:
http://en.wikipedia.org/wiki/Rounding

Go watch Superman III for another lesson in rounding.

Regards,

Joergen Bech

---snip---
1,00: 0,99
1,01: 0,99
1,02: 0,99
1,03: 0,99
1,04: 0,99
1,05: 0,99
1,06: 1,09
1,07: 1,09
1,08: 1,09
1,09: 1,09
1,10: 1,09
1,11: 1,09
1,12: 1,09
1,13: 1,09
1,14: 1,09
1,15: 1,19
1,16: 1,19
1,17: 1,19
1,18: 1,19
1,19: 1,19
1,20: 1,19
1,21: 1,19
1,22: 1,19
1,23: 1,19
1,24: 1,19
1,25: 1,19
1,26: 1,29
1,27: 1,29
1,28: 1,29
1,29: 1,29
1,30: 1,29
1,31: 1,29
1,32: 1,29
1,33: 1,29
1,34: 1,29
1,35: 1,39
1,36: 1,39
1,37: 1,39
1,38: 1,39
1,39: 1,39
1,40: 1,39
1,41: 1,39
1,42: 1,39
1,43: 1,39
1,44: 1,39
1,45: 1,39
1,46: 1,49
1,47: 1,49
1,48: 1,49
1,49: 1,49
1,50: 1,49
1,51: 1,49
1,52: 1,49
1,53: 1,49
1,54: 1,49
1,55: 1,59
1,56: 1,59
1,57: 1,59
1,58: 1,59
1,59: 1,59
1,60: 1,59
1,61: 1,59
1,62: 1,59
1,63: 1,59
1,64: 1,59
1,65: 1,59
1,66: 1,69
1,67: 1,69
1,68: 1,69
1,69: 1,69
1,70: 1,69
1,71: 1,69
1,72: 1,69
1,73: 1,69
1,74: 1,69
1,75: 1,79
1,76: 1,79
1,77: 1,79
1,78: 1,79
1,79: 1,79
1,80: 1,79
1,81: 1,79
1,82: 1,79
1,83: 1,79
1,84: 1,79
1,85: 1,79
1,86: 1,89
1,87: 1,89
1,88: 1,89
1,89: 1,89
1,90: 1,89
1,91: 1,89
1,92: 1,89
1,93: 1,89
1,94: 1,89
1,95: 1,99
1,96: 1,99
1,97: 1,99
1,98: 1,99
1,99: 1,99
 
Mark S. Milley said:
Yeah, that was definately much easier than my solution.

So... In what instance would this give a different result than mine?

Apparently Blind,

-Mark

I don't know about easier. Just a different way of getting to the same
place.
Also, sometimes doing the math helps centre one's perspective. I call it
'simple' because it's nothing like an algorithm for nailing the trig
function bugs in a 3D polar rotation. Normally a fairly strightforward piece
of math that on paper produces a single formula; The coding requires four
separate formulas because the canned trig functions cannot even correctly
sign the appropriate quadrant. As you can imagine, I'm a little cautious of
invoking canned subroutines because:

1. I don't know what's in them,
2. Sometimes they are slower than the derived subroutine or function,
3. Occasionally they are just plain old dead wrong.

I have to admit, I'd be disappointed if there was any difference in output,
or if your example was slower than mine. Your example did one thing for me,
and that was to emphasise the fact that there are many more improved
functions than I realised. However, reworking canned functions is good
practice for when there is no canned function or method to call on...

By the way, the debug.writeline(myfunction(myvariable)) doesn't seem to work
the way it used to as debug.print(myfunction(myvariable)) did in VB6. Am I
missing a setting or reference?
 
On Sun, 8 Jul 2007 17:06:26 +1000, "Number 11950 - GPEMC! Replace


---snip---
By the way, the debug.writeline(myfunction(myvariable)) doesn't seem to work
the way it used to as debug.print(myfunction(myvariable)) did in VB6. Am I
missing a setting or reference?

Debug.Print is still available and is exactly equivalent to
Debug.WriteLine.

They both invoke a call to

System.Diagnostics.TraceInternal.WriteLine.

Absent from VS2003 but present in VS2005. Not in a
compatibility namespace, but in one of the core ones
for no good reason at all. I can understand parameter
overloading, but providing two methods that do exactly
the same thing is just plain wrong. Microsoft giving in to
popular demand again, I guess.

But anyway ...

Check Tools -> Options -> Debugging -> General
("Redirect all Output ...") to find out if the text goes
to the Immediate or Output window.

Regards,

Joergen Bech
 
Ah-ha! I finally found the problem; try this:

Dim ups As Integer = 0
Dim downs As Integer = 0
Dim totalcount As Integer = 0
For value As Decimal = 1D To 1.99D Step 0.01D
Dim roundedvalue As Decimal = Math.Round(value, 1,
MidpointRounding.AwayFromZero) - 0.01D 'This is where the magic
happens
Debug.WriteLine(value.ToString("0.00") & ": " &
roundedvalue.ToString("0.00"))
totalcount = totalcount + 1
If roundedvalue < value Then
downs = downs + 1
Else
ups = ups + 1
End If
Next


Debug.WriteLine("------------------------")
Debug.WriteLine("Total: " & totalcount.ToString)
Debug.WriteLine("Ups: " & ups.ToString)
Debug.WriteLine("Downs: " & downs.ToString)



Not knowing the inner workings of the entire framework, I wasn't aware
that you had to tell Math.Round to use the traditional, elementary
school method of rounding a number. The default way doesn't make a bit
of sense to me.

Anyway, I still feel that my solution
Result = Math.Round(X, 1, MidpointRounding.AwayFromZero) - 0.01
is cleaner and easier to understand than
Result = Int(10 * (X + 0.05)) / 10 - 0.01

Happy Coding,

-Mark
 
Not knowing the inner workings of the entire framework, I wasn't aware
that you had to tell Math.Round to use the traditional, elementary
school method of rounding a number. The default way doesn't make a bit
of sense to me.

It makes perfect sense and is the correct choice for the default
behavior, even if it is not appropriate for all applications.

If the resolution is 0.1, you would have

n.1, n.2, n.3, n.4 (rounded down to n)
n.5 (rounded up or down)
n.6, n.7, n.8, n.9 (rounded up to n+1)

So: 4 down, 4 up, and one going either way.

If n.5 was always rounded up, you would have
4 down and 5 up, i.e. the results would be
skewed to one side.

Did you read the Wikipedia article?
Anyway, I still feel that my solution
Result = Math.Round(X, 1, MidpointRounding.AwayFromZero) - 0.01
is cleaner and easier to understand than
Result = Int(10 * (X + 0.05)) / 10 - 0.01

That's the way I would have written it. Though I would
have written the more direct Math.Floor instead of Int.

Regards,

Joergen Bech
 
Did you read the Wikipedia article?

Yes; and in my entire professional history, during which I have
created several programs for the accounting departments of several
companies, I have never had a request where they wanted to "round-to-
even". I'm surprised to learn that this is the default behavior in the
framework's Math.Round function, so I thank you for pointing that
out.

I can appreciate the need for this when dealing with statistical data,
where balance is important, but for rounding some prices, as in the
inital request, I think (arbitrarily, IMHO) rounding a number down
because the precedent is an even number is, for most people, counter-
intuitive. For instance, if Jonathan's boss saw the results of a round-
to-even price modifications, I think he would be puzzled to say the
least; then again, I'm assuming he's not a statistician.

Peace,

-Mark
 
If n.5 was always rounded up, you would have
4 down and 5 up, i.e. the results would be
skewed to one side.

I still don't understand the viewpoint here.
Wikipedia:
With all rounding schemes there are two possible outcomes: increasing the rounding digit by one or leaving it alone.

1.0->1 No Change on Rounding Digit
1.1->1 No Change on Rounding Digit
1.2->1 No Change on Rounding Digit
1.3->1 No Change on Rounding Digit
1.4->1 No Change on Rounding Digit
1.5->2 Rounding Digit Changed
1.6->2 Rounding Digit Changed
1.7->2 Rounding Digit Changed
1.8->2 Rounding Digit Changed
1.9->2 Rounding Digit Changed

Therefore, we have a 50/50 split; 5 changed, and 5 unchanged.

Let's expand this out to a greater level of precision:

1.0000 to 1.4999 = 1 : 5000 unchanged
1.5000 to 1.9999 = 2 : 5000 changed

Are we really biased upward? I suppose--but the whole nature of
rounding is that it makes values less precise, to increase usability.
If we wanted to be perfectly accurate, we should always deal with as
precise of values as possible.

Ah well, maybe I just have a glass-half-full approach to life.

Fin,

-Mark
 
No. Your error is that you are including 1.0000 in the
"down" count. You should have written

1.0000 (no change)
1.0001-1.4999 (4999 down)
1.5000-1.9999 (5000 up)

Whoops! And on that note, let me correct my test program
myself before anyone else does:
---snip---
Private Sub RoundingTest()
Dim ups As Integer = 0
Dim downs As Integer = 0
Dim totalcount As Integer = 0
For value As Decimal = 1D To 1.99D Step 0.01D
Dim roundedvalue As Decimal = Math.Round(value, 1) - 0.01D
If roundedvalue <> (value - 0.01D) Then
Debug.WriteLine(value.ToString("0.00") & ": " &
roundedvalue.ToString("0.00"))
totalcount = totalcount + 1
If roundedvalue < value Then
downs = downs + 1
Else
ups = ups + 1
End If
End If
Next

Debug.WriteLine("------------------------")
Debug.WriteLine("Total: " & totalcount.ToString)
Debug.WriteLine("Ups: " & ups.ToString)
Debug.WriteLine("Downs: " & downs.ToString)

End Sub
---snip---

Now we get 45 ups and 45 downs. No bias, due to the default
round-to-even method.

Had we used

Dim roundedvalue As Decimal = Math.Round(value, 1,
MidpointRounding.AwayFromZero) - 0.01D

the result would have been 50 ups and 40 downs.

I think this thread is well and truly exhausted now.

Regards,

Joergen Bech
 
Back
Top