displaying Decimal numbers
Monkey Forums/Monkey Programming/displaying Decimal numbers
| ||
Hi, I am using floats for numbers during calculations, but want to round them up when I want to display them. So 10.120000000099 looks like 10.1 I found no rounding function built in, but found this online (which is fairly standard practice for rounding) Function Round:Float(N:Float, DecimalPlaces:Int) Return Float(Int(N * Pow(10.0,DecimalPlaces))) / Pow(10.0,DecimalPlaces) End Function The trouble is that the returned number is still a float! So yes, 10.12 might get rounded nicely to 10.1, but when I display it it sometimes displays as 10.10000000094324. How can I display a number with a decimal place without the grief that displaying floats can give? Many thanks |
| ||
Off the top of my head, something like the below should work: 1) Convert rounding result to a string 2) Split on decimal point into whole and fractional parts 3) Recombine whole + "." + fractional[..DecimalPlaces] |
| ||
this should work(untested):n:float = 10.12000099 n = (int(n*10)/10.0) That function in your post works for me also. |
| ||
Tested both versions and neither round the decimal places correctly, they only display x places. I spent a few minutes racking my brain and came up with this, it rounds correctly to any number of decimal places displaying a float. (HTLM5 tested only) Possibly could be written more elegantly but it works... 10.23 will round to 10.2 10.25 will round to 10.2 10.26 will round to 10.3 [monkeycode] Function Round : Float( value : Float, places : Int = 1 ) Local div : Float = Pow( 10.0, places ) Local a : Float = value * div Local b : Float = Floor( a ) If a - b <= 0.5 Return b / div Return Ceil( a ) / div End Function [/monkeycode] If anyone knows a shorter/cleaner way please can you post the code, I've always wondered how to do this. |
| ||
Hi, both examples though still return a float. This is still a problem and numbers can sometimes look wrong (ie 10.120000000002345) even after rounding, particularly when output to Windows or iOS rather than to HTML5 I think returning a string is the only option in the absence of a decimal type. |
| ||
For other targets you can probably still use the Round function but then trim the string to x decimal places as well to hide the float trailing errors.... |
| ||
Function Format:String(num:Float, places:Int, removeZeros:Bool=True) Local txt:String = String(num) Local pointPos:Int = txt.Find(".") If pointPos = -1 Return txt txt = txt[..pointPos+places+1] If removeZeros While txt[txt.Length-1] = 48 txt = txt[..txt.Length-1] End If txt[txt.Length-1] = 46 txt = txt[..txt.Length-1] End Return txt End |
| ||
As long as the function returns a float, it won't be able to properly display rounded floats. Example: Function Main() Print Round(Sqrt(2), 1) End Function Round:Float(value:Float, places:Int = 1) Local div : Float = Pow( 10.0, places ) Local a : Float = value * div Local b : Float = Floor( a ) If a - b <= 0.5 Return b / div Return Ceil( a ) / div End Function Output: 1.3999999999999999 A display-round function, in my opinion, shoud return a formatted string with internal rounding done in a way it handles the float rounding precission properly, instead of bypassing it or, even worse, making it happen a lot before, like in the sample I've just shown. EDIT: I suggest this implementation (may be improved): [monkeycode]Function Round:String(value2:Float, places:Int = 1, decSymbol:Int = "."[0]) 'We convert the number to a truncated version of it, using a integer representation of places + 1 chars: Local rounding:Int = math.Abs(value2 * math.Pow(10, places + 1)) 'We round the value, according to latest character: If rounding Mod 10 >= 5 rounding += 10 EndIf 'We convert this result to a String, knowing the number of digits and knowing where to place the decimal symbol separator: Local result:String = rounding 'If the number begins with a dot, we put the 0, so it gets 0.45 instead of .45 wich is a lot ugglier on display: If result.Length = places + 1 Then result = "0" + result 'We create a buffer to store the resulting rounded number string: Local buffer:Int[] = New Int[result.Length] 'We iterate throug original number, putting the decimal separator in place, and therefore ignoring latest digit (places + 1) so it gets the correct number after rounding. For Local i:Int = 0 Until buffer.Length If i < buffer.Length - places - 1 Then buffer[i] = result[i] ElseIf i = buffer.Length - places - 1 buffer[i] = decSymbol Else buffer[i] = result[i - 1] End End 'We return the generated rounded number string, according to original number sign: If value2 >= 0 Then Return String.FromChars(buffer) Else Return "-" + String.FromChars(buffer) EndIf End[/monkeycode] |
| ||
or x10 and call it an int |