Android Question Round2 limits/errors

Roger Daley

Well-Known Member
Licensed User
Longtime User
Hi all,

A question on the limits of Round2(Number, Decimalplaces). I have found that Round2 returns incorrect results if the combination of Number and Decimalplaces becomes large.
For example:
1. Round2(1.23456789, 18) produces the expected result but Round2(1.23456789, 20) gives 0.09223372
2. Round2(123456.123456, 14) produces 92.23372037E3
The bigger the "Number" the smaller the possible "Decimalplaces"
Obviously the internal process of Round2 is producing "out of range numbers" without a trap/limit/flag.

My question is, does anyone know how to determine the limits the Round2 arguments to an acceptable combination range?

Any help much appreciated

Regards Roger
 
Hi all,

Solution has come to mind, I will post here for others.

Sub MaxRound(Numb)
'Sub to determine the maximum number of decimal places to which "Numb" can be rounded using
'Round2 (Number As Double, DecimalPlaces As Int) As Double

Dim temp1 As Double
Dim MaxRounding As Int
temp1 = Logarithm(Numb,10) 'Take logarithm of number to be rounded
temp1 = Round2(temp1,0) 'Resulting Logarithm rounded to an interger
MaxRounding = 18 - temp1 'Calculate maximum rounding digit as interger
Msgbox(MaxRounding, "Maximum number of digits to which the number can be rounded")
End Sub


Regards Roger
 
Upvote 0
Im working with graphs and need to roun the max value for the Y axis.
If I have for example max=280, which function to use to obtain 300?
thanks
 
Upvote 0
Alberto,

Seeing Erels reply I think I now understand what you are trying to do.

Code: Copy
Dim roundedValue As Int = 100 * Round(value / 100)
Value=Max=280
roundedValue=300    'Y Axis  fits Max
       or
Value=Max=240
roundedValue=200    'Y Axis  does not fit Max

I suggest you try the Ceil function instead of the Round function. If your max=240 using the Round function would give a Y axis of 200.


Below "N" is determined by the size of Max. IE Max >=10 and Max< 100 "N"=10 Etc.

Code: Copy
Dim YAxisValue As Int = N * Ceil(value / N)
N=100
Value=Max=280
YAxisValue=300    'Y Axis  fits Max
       or
Value=Max=240
YAxisValue=300    'Y Axis  fits Max

Regards Roger
 
Upvote 0
How about this that will take care of both positive and negative number situations:
Code: Copy
Log("MyRound:" & RoundValue(161.93)) 'displays 200
Log("MyRound:" & RoundValue(906.8)) 'displays 1000
Log("MyRound:" & RoundValue(-70)) 'displays -100
Log("MyRound:" & RoundValue(280)) 'displays 300
Log("MyRound:" & RoundValue(-280)) 'displays -300
Code: Copy
Sub RoundValue(x As Double) As Int
   If x > 0 Then
       Return 100 * Ceil(x / 100)
   Else
       Return 100 * Floor(x / 100)
   End If
End Sub
 
Upvote 0
And for those who like shoving as much execution as possible into one line at the expense of readability:
Code: Copy
Sub RoundedValue(x As Double) As Int
     Return (x/Abs(x)) * 100 * Ceil(Abs(x)/100)
End Sub

If your y-axis could be any value within the Int range, you probably don't want to be rounding up to the next hundred. If value=1,854,025, you probably don't want your y-axis to go up to 1,854,100, you probably want it to go up to 2,000,000.
Code: Copy
Sub RoundedValueGeneral(x As Double) As Int
    Return (x/Abs(x)) * Power(10,Floor(Logarithm(Abs(x),10))) * Ceil(Abs(x)/Power(10,Floor(Logarithm(Abs(x),10))))
End Sub
 
Upvote 0
And for those who like shoving as much execution as possible into one line at the expense of readability:
Code: Copy
Sub RoundedValue(x As Double) As Int
     Return (x/Abs(x)) * 100 * Ceil(Abs(x)/100)
End Sub

If your y-axis could be any value within the Int range, you probably don't want to be rounding up to the next hundred. If value=1,854,025, you probably don't want your y-axis to go up to 1,854,100, you probably want it to go up to 2,000,000.
Code: Copy
Sub RoundedValueGeneral(x As Double) As Int
    Return (x/Abs(x)) * Power(10,Floor(Logarithm(Abs(x),10))) * Ceil(Abs(x)/Power(10,Floor(Logarithm(Abs(x),10))))
End Sub


Roycefer,

Re-looked at this again and I have say I am impressed, especially if you wrote that line in one breath. ... and you have simplified a different problem for me. Thanks.

Roger
 
Upvote 0
Glad I could help.

The RoundedValueGeneral() sub is an interesting case study in code style choices. While it is certainly the tersest implementation of that logic (it all executes in one line, after all), it is probably not the most efficient implementation. We are forcing the processor to calculate Power(10,Floor(Logarithm(Abs(x),10))) twice, whereas if we did this:
Code: Copy
Sub RoundedValueGeneral(x As Double) As Int
     Dim powfllog as Double = Power(10,Floor(Logarithm(Abs(x),10)))
     Return (x/Abs(x)) * powfllog * Ceil(Abs(x)/powfllog)
End Sub
the processor only has to calculate it once and retrieve it from L1 cache twice, possibly making it a bit faster. Terse isn't always most efficient. You should add that to your B4Zen wisdom.
 
Upvote 0
Back
Top