Number Format – Thousand Separator in AS3

Here’s a short number format function I wrote to easily paste in your code when needed. It’s really handy for currency formatting.
The first parameter (number:*) can be a Number, int, uint or a String class instance.
The last parameter (siStyle:Boolean) specifies whether to use the International System of Units or not. SI units have points between the thousands and a comma for the seperator (123.456.789,01). Putting siStyle as false reverses that behaviour (123,456,789.01).

It’s really ugly by design since I wanted it to be a single, tiny function. There’s loads of prettier/faster code samples out there.

function numberFormat(number:*, maxDecimals:int = 2, forceDecimals:Boolean = false, siStyle:Boolean = false):String {
    var i:int = 0, inc:Number = Math.pow(10, maxDecimals), str:String = String(Math.round(inc * Number(number))/inc);
    var hasSep:Boolean = str.indexOf(".") == -1, sep:int = hasSep ? str.length : str.indexOf(".");
    var ret:String = (hasSep && !forceDecimals ? "" : (siStyle ? "," : ".")) + str.substr(sep+1);
    if (forceDecimals) for (var j:int = 0; j <= maxDecimals - (str.length - (hasSep ? sep-1 : sep)); j++) ret += "0";
    while (i + 3 < (str.substr(0, 1) == "-" ? sep-1 : sep)) ret = (siStyle ? "." : ",") + str.substr(sep - (i += 3), 3) + ret;
    return str.substr(0, sep - i) + ret;
}

Tags: , , , , , , , ,

17 Responses to “Number Format – Thousand Separator in AS3”

  1. Gustavo GarcĂ­a Says:

    I like your snippet, thank you. Only thing there’s an error which leads to one decimal place less than expected.
    WRONG:
    for (var j:int = 0; j < maxDecimals – (str.length – sep); j++)
    RIGHT:
    for (var j:int = 0; j < maxDecimals – (str.length – 1 – sep); j++)

  2. Flassari Says:

    Aaah, you’re absolutely right! It’s fixed now.

    To hold onto compactness I changed

    for (var j:int = 0; j < maxDecimals - (str.length - sep); j++)

    to

    for (var j:int = 0; j <= maxDecimals - (str.length - sep); j++)

    Thanks for spotting that =)

  3. John Says:

    You’ve also got the comma and decimal around the wrong way.

  4. Flassari Says:

    No, that’s what the siStyle property is for, you can actually choose the metric SI style (default true because of majority) or non-SI style (false) that’s in use in mostly Burma (Myanmar), Liberia, and the United States.

  5. nizzle Says:

    Thanks, I was just looking for something like this. Nice code, also.

  6. Torben Says:

    I don’t see what was wrong with your original Deciaml code. When I test it your first line works – the second ads one decimal too many.

  7. Flassari Says:

    Torben, I found the error you were talking about; it only happened when you passed in whole numbers.
    It’s been fixed now, thanks for spotting it =)

  8. Torben Says:

    Great, thanks Flassari

  9. DanielSig Says:

    Hey, I added a little tweak of mine to your function. What it does is that it indents the returning string with indentUnit so that the length of the string minus decimals becomes forceLength.

    This can be useful when you intend to align a vertical list of numbers so that the decimal points are in a straight line.

    Note: unless you specify the forceLength parameter as a uint higher than 0, this function behaves just like the original function made by Flassari.

    function numberFormat(number:*, maxDecimals:int = 2, forceDecimals:Boolean = false, siStyle:Boolean = true, forceLength:uint = 0, indentUnit:String = " "):String {
    	var i:int = 0, inc:Number = Math.pow(10, maxDecimals), str:String = String(Math.round(inc * Number(number))/inc), indent:String = "";
    	var hasSep:Boolean = str.indexOf(".") == -1, sep:int = hasSep ? str.length : str.indexOf(".");
    	var ret:String = (hasSep && !forceDecimals ? "" : (siStyle ? "," : ".")) + str.substr(sep+1);
    	if (forceDecimals) for (var j:int = 0; j <= maxDecimals - (str.length - (hasSep ? sep-1 : sep)); j++) ret += "0";
    	while (i + 3 < (str.substr(0, 1) == "-" ? sep-1 : sep)) ret = (siStyle ? "." : ",") + str.substr(sep - (i += 3), 3) + ret;
    	if(forceLength != 0) for(j = sep + i / 3; j < forceLength; j++) indent += indentUnit;
    	return indent + str.substr(0, sep - i) + ret;
    }
  10. bractar Says:

    nice functionality but I hate your formatting. It isn’t clear enough to be updated easily. You don’t need to show that you can program like a nasa guy when you give a function on the web. Most people who will use your function will be beginners…
    But thank you for sharing it

  11. Flassari Says:

    The formatting was done on purpose. I know it’s massively compressed and horrible to read, but it’s supposed to be small and convenient to paste into timeline or code. There were other resources which had dedicated classes which are easily changeable and commented (like for beginners) at the time I made this (and still are), but I didn’t want a whole class when I just wanted something quick and small to insert into the timeline.
    I also don’t recommend this code for mass number processing since it is not at all optimized for speed, only compactness.

  12. Julianne Santos Says:

    Hi Flassari!
    You saved me a lot of time!
    Many many thanks from Brasil!

  13. Gamefreak Says:

    great function, thanks alot

  14. Yu-Chung Chen Says:

    works perfectly, thanks.

  15. Mgcool Says:

    This is exactly what i was looking for. Regards. MX

  16. Gorjan Says:

    Great stuff. Thanks for saving me some time when I had none :)

  17. Spiroszaf Says:

    Hey! Thanks alot for sharing this. It helped me big time!