How to round float to x decimal places?

This is what I tried (doesn’t work).

Int(floatNumber*1000.0)/1000.0

There is the Ceil (up), Floor (down) and Round (nearest integer) function to round a number.

1 Like

Thanks, I missed the whole “failable functions” part.

Round() only rounds to a whole number, what I need is to round to 3 decimal places.

Can you please give me an example?
Value = 6.456123456
and my desired output is 6.456 as float or as string (“6.456”).

Below is my attempt, when I divide the integer with 1000, and I get a rational type, and there is no way to convert a rational to either float or string.

        var myFloatNumber : float = 6.456123456 * 1000.0
        var myIntNumber : int = 0
        var myFinalNumber : string = ""

        if (Value := Round[myFloatNumber]):
           set myIntNumber = Value      

        if (Value : rational = myIntNumber / 1000):
            set myFinalNumber = ToString(Value)
            
        
        Print(myFinalNumber)

@ChrisAI

This mostly comes down to a problem of converting between ints and floats in Verse. One thing you might have been missing is that you can multiply an int by 1.0 to turn it into a float. Here is a version of your original code with that + rounding integrated in.

QuickTest():logic =
    if:
        ((Round[10.12345 * 1000.0] * 1.0) / 1000.0) = 10.123
    then:
        return true
    else:
        return false

I also gave a quick go at writing a more generic version

RoundToDecimalPlaces(Value:float, DecimalPlaces:int)<varies><decides>:float =
    DecimalPlaces >= 0
    Multiplier := Pow(10.0, DecimalPlaces * 1.0)
    RoundedValues := Round[Value * Multiplier] * 1.0
    return RoundedValues / Multiplier

QuickTest():logic =
    if:
        RoundToDecimalPlaces[10.12345, 0] = 10.0
        RoundToDecimalPlaces[10.12345, 1] = 10.1
        RoundToDecimalPlaces[10.12345, 2] = 10.12
        RoundToDecimalPlaces[10.12345, 3] = 10.123
        RoundToDecimalPlaces[10.12345, 4] = 10.1234
        RoundToDecimalPlaces[10.12345, 5] = 10.12345
        RoundToDecimalPlaces[10.12345, 6] = 10.123450

        RoundToDecimalPlaces[10.56789, 0] = 11.0
        RoundToDecimalPlaces[10.56789, 1] = 10.6
        RoundToDecimalPlaces[10.56789, 2] = 10.57
        RoundToDecimalPlaces[10.56789, 3] = 10.568
        RoundToDecimalPlaces[10.56789, 4] = 10.5679
        RoundToDecimalPlaces[10.56789, 5] = 10.56789
        RoundToDecimalPlaces[10.56789, 6] = 10.56789
    then:
        return true
    else:
        return false
3 Likes

If you want to do it with a string, perhaps to show it on screen (ex. with a text_block widget), then here is a function I wrote that creates a string with a specified number of decimal places from a float.

    GetRoundedString<private>(Input : float, NumDigitsAfterDecimal : int) : string =
        if:
            Multiplier := Pow(10.0, NumDigitsAfterDecimal * 1.0)
            RoundedValue := RoundedTickRate := float[Round[Input*Multiplier]*1.0] / Multiplier
            BeforeDecimal := Floor[RoundedValue]
            AfterDecimal := Abs(Round[(RoundedValue - BeforeDecimal*1.0)*Multiplier])
            var AfterDecimalString : string = ToString(AfterDecimal)

            #pad with leading zeroes
            for (It := 0..(NumDigitsAfterDecimal-AfterDecimalString.Length-1)):
                set AfterDecimalString = array{'0'} + AfterDecimalString
        then:
            "{BeforeDecimal}.{AfterDecimalString}"
        else:
            ToString(Input)
8 Likes

This is fantastic, thanks for sharing!

2 Likes

Hello there,

Any idea on making this function working with negatives values ?

I mean im trying to round a big negative float (-13 800 000 000.0000) but when i apply the function it return me “-14.2 B” as a string obviously.

Honestly, i dont understand why it returns me this value

Im expecting to get “-13.8 B” and not “-14.2 B”

I tested it with positive value and its return the right value.

here is my code

RefreshUI(Agent:agent)<suspends>:void=
        Print("Starting to Refresh")
        if(TextBlock := ResourceTextBlockPerAgent[Agent]?):
            loop:
                Sleep(RefreshRate)
                IncomeRateString: []char = ToString(incomeRate) 
    
                if (Wallet >= 1000000000.0 or Wallet <= -1000000000.0):
                    if(Wallet < 1000000000000.0 or Wallet > -1000000000000.0):
                            set WalletFloat = Wallet / 1000000000.0
                            set WalletString = GetRoundedString(WalletFloat, 1) + Billion
                            TextBlock.SetText(S2M("{WalletString}  |  {incomeRate}"))

                else if (Wallet >= 1000000.0 or Wallet <= -1000000.0):
                        if(Wallet < 1000000000.0 or Wallet > -1000000000.0):
                            set WalletFloat = Wallet / 1000000.0
                            set WalletString = GetRoundedString(WalletFloat, 1) + Million
                            TextBlock.SetText(S2M("{WalletString}  |  {incomeRate}"))

                else if (Wallet >= 1000.0 or Wallet <= -1000.0):
                        if(Wallet < 1000000.0 or Wallet > -1000000.0):
                            set WalletFloat = Wallet / 1000.0
                            set WalletString = GetRoundedString(WalletFloat, 1)  + Kilo                   
                            TextBlock.SetText(S2M("{WalletString}   |  {incomeRate}"))

                else if (Wallet < 1000.0 and Wallet > -1000.0):
                        set WalletFloat = Wallet
                        set WalletString = GetRoundedString(WalletFloat, 1)
                        TextBlock.SetText(S2M("{WalletString}  |  {incomeRate}"))

EDIT : i just found out on my UI that when my decimal is between 5 and 9, i will get this bug, but when my decimal is between 0 and 4 everything is working well.

So i think the problem is in the rounding method but idk how to solve that

Okay so I resolved my problem.

I had to use Ceil instead of Floor.

    GetRoundedString(Input : float, NumDigitsAfterDecimal : int) : string =

            if:
                Multiplier := Pow(100.0, NumDigitsAfterDecimal * 1.0)
                RoundedValue :=  RoundedTickRate := float[Ceil[Input*Multiplier]*1.0] / Multiplier
                BeforeDecimal := Ceil[RoundedValue]
                AfterDecimal := Abs(Ceil[(RoundedValue - BeforeDecimal*1.0)*Multiplier])
                var AfterDecimalString : string = ToString(AfterDecimal)

                #pad with leading zeroes
                for (It := 0..(NumDigitsAfterDecimal-AfterDecimalString.Length-1)):
                    set AfterDecimalString = array{'0'} + AfterDecimalString
            then:
                "{BeforeDecimal}.{AfterDecimalString}"
            else:
                ToString(Input)
1 Like