10

Duplicate of this one.

What would you use to pad zeroes to the left of a number in Flex/AS3?

Is there an equivalent to printf or NumberFormat that does this?

I'm looking for the nicest implementation of this or something similar:

public function zeroPad(number:int, width:int):String {
    // number = 46, width = 4 would return "0046"
}
Community
  • 1
  • 1
lpfavreau
  • 12,871
  • 5
  • 32
  • 36
  • 1
    It is indeed a duplicate although I never found it with the search engine because it doesn't talk about zero, padding, number formating and has the wording Ruby-like in the title. – lpfavreau Mar 20 '09 at 15:53
  • Yes, it's rather unfortunate. Hope your trouble's sorted out now. – dirkgently Mar 20 '09 at 16:21
  • It was indeed what I was looking for. Well, for a built-in function first and the best implementation if no built-in function existed. Thanks for the link. – lpfavreau Mar 20 '09 at 18:41
  • I don't think it is a duplicate. The solution might be the same, but the question is different. – Richard Garside Sep 27 '10 at 22:14
  • ActionScript should be more mature than this and have their own padding method. :( – Rudy Dec 06 '11 at 06:31

8 Answers8

26
public function zeroPad(number:int, width:int):String {
   var ret:String = ""+number;
   while( ret.length < width )
       ret="0" + ret;
   return ret;
}
Phil
  • 851
  • 6
  • 9
3

Performance-wise, I prefer using a String constant and substr, like this:

package {
    public class Helper {
        private static const _ZEROS:String = "0000000000000000000000000000000000000000"; // 40 zeros, shorten/expand as you wish

        /*
         * f: positive integer value
         * z: maximum number of leading zeros of the numeric part (sign takes one extra digit)
         */
        public static function uint_Zeropadded(f:uint, z:int = 0):String {
            var result:String = f.toString();
            while (result.length < z)
                result = _ZEROS.substr(0, z - result.length) + result;
            return result;
        }
    }
}

The String constant has very little footstamp compared to the performance draw-backs of extending the string one by one digit numerous times. In most cases (up to 40 zeros in this example) number of instructions is the same for all calls.

2

Phil's variant as an elegant recursion:

public function zeroPad (number:String, width:int):String {
    if (number.length < width)
        return "0" + zeroPad(number, width-1);
    return number;
}

I don't know of its performance on AS3 but it sure looks cooler! :-)

Community
  • 1
  • 1
cregox
  • 17,674
  • 15
  • 85
  • 116
  • recursion should be avoided whenever possible and it almost always is possible – Bron Davies Oct 13 '12 at 04:40
  • 1
    @stinkbutt in this case, *recursion* makes more sense. I believe it's something not taught in many programming courses because it's not as intuitive as a *loop* and, in fact, it is more limiting than a loop. But saying *it should be avoided whenever possible* is a bit extreme. I'd say ***use recursion with caution and keep it small***, because it can get really complicated for no good reason. – cregox Oct 15 '12 at 12:33
  • The reason I say that is because a stack overflow is more likely when you use recursion - it may not be apparent right away but in the long term, you can inadvertently create a situation where a lot of data coupled with even just a couple of recursive methods will bring your application or script to its knees. – Bron Davies Jan 09 '13 at 18:01
  • @stinkbutt well, if that's true to actionscript I wouldn't know, and then I have to agree with you to avoid it always, because it is always avoidable. But recursion exists in programming languages prior to *loops* and it should never be "more likely" to generate overflows with 'em. – cregox Jan 09 '13 at 18:22
  • The reason to use recursion is for clarity when the problem is better suited to reducible problems. An iterative approach is nearly always faster and more efficient than a recursive approach. – FlavorScape Sep 27 '13 at 00:29
  • Recursing puts the memory on the stack (afterall, it has to retain all the previous state for each iteration), hence potential for stack overflow if the depth is high, or the memory low. – FlavorScape Sep 27 '13 at 00:45
  • @FlavorScape nope, [iterative isn't nearly nor farly always faster](http://stackoverflow.com/a/2185573/274502). But there's more to it and it's already ["discussed" on another question](http://stackoverflow.com/questions/72209/recursion-or-iteration). In short I like this saying: "write it the way that's clearer to read". I think in this case Phil is easier to read, but I only wrote this answer because I was feeling like going recursive! ;-) – cregox Sep 27 '13 at 00:49
  • I believe as3 is of the family where a new stackframe is created for each recursion, no? That's a lot of memcopy and a lot of mem for deep recursions. obviously not the case here of course. – FlavorScape Sep 27 '13 at 01:02
1
public static function getFormatedValue(num:Number, roundDecimalPlace:Number=2, showLastZerosInDecimalPlaces:Boolean = false, decimalSeparator:String=".", thousandsSeparator:String=",", currency:String="$"):String
{
  //assigns true boolean value to neg in number less than 0
  var neg:Boolean = (num < 0);

  //make the number positive for easy conversion
  num = Math.abs(num)

  var roundedAmount:String = String(num.toFixed(roundDecimalPlace));

  //split string into array for dollars and cents
  var amountArray:Array = roundedAmount.split(".");
  var dollars:String = amountArray[0]
  var cents:String = amountArray[1]

  //create dollar amount
  var dollarFinal:String = ""
  var i:int = 0
  for (i; i < dollars.length; i++)
  {
    if (i > 0 && (i % 3 == 0 ))
    {
      dollarFinal = thousandsSeparator + dollarFinal;
    }

    dollarFinal = dollars.substr( -i -1, 1) + dollarFinal;
  }       

  //create Cents amount and zeros if necessary
  var centsFinal:String;

  if(showLastZerosInDecimalPlaces)
  {
    centsFinal = String(cents);

    var missingZeros:int = roundDecimalPlace - centsFinal.length;

    if (centsFinal.length < roundDecimalPlace)
    {
      for (var j:int = 0; j < missingZeros; j++) 
      {
        centsFinal += "0";
      }
    }
  }
  else
  {
    if(Number(cents) != 0)
    {
      centsFinal = String(String(Number("0."+cents)).split(".")[1]);
    }
    else
    {
      roundDecimalPlace = 0;
    }
  }

  var finalString:String = ""

  if (neg)
  {
    finalString = "-"+currency + dollarFinal
  } else
  {
    finalString = currency + dollarFinal
  }

  if(roundDecimalPlace > 0)
  {
    finalString += decimalSeparator + centsFinal;
  } 

  return finalString;
}
1

Very short example of zero padding routine (AS2)...

    Convert = function(Minutes) {
       return ('00'+String(int(Minutes/60)%24)).substr(-2,2);
    }
Bert
  • 61
  • 4
0

A very compact solution:

public function zeroPad(s:String,pad:int):String {
    for(;s.length<pad;s='0'+s);
    return s;
}
0

I do maintain a printf in AS3: Unfortunately stack overflow won't let me post links, but if the google code's project name is printf-as3

Feedback is always welcome.

--

http://code.google.com/p/printf-as3/

lpfavreau
  • 12,871
  • 5
  • 32
  • 36
Arthur Debert
  • 10,237
  • 5
  • 26
  • 21
0
/** 
 * originally by Chris Agiasotis @ http://agitatedobserver.com/as3-currency-formatter/
 * improved by Joseph Balderson @ http://www.joeflash.ca
 */
package
{
    public class CurrencyFormat
    {
        public function CurrencyFormat(){ }

        public function getCurrency(num:Number,
                    decimalSeparator:String=".",
                    decimalPlace:Number=2,
                    currency:String="$",
                    thousandsSeparator:String=","
                ):String
        {
            //assigns true boolean value to neg in number less than 0
            var neg:Boolean = (num < 0);

            //make the number positive for easy conversion
            num = Math.abs(num)

            var roundedAmount:String = String(num.toFixed(decimalPlace));

            //split string into array for dollars and cents
            var amountArray:Array = roundedAmount.split(".");
            var dollars:String = amountArray[0]
            var cents:String = amountArray[1]

            //create dollar amount
            var dollarFinal:String = ""
            var i:int = 0
            for (i; i < dollars.length; i++)
            {
                if (i > 0 && (i % 3 == 0 ))
                {
                    dollarFinal = thousandsSeparator + dollarFinal;
                }

                dollarFinal = dollars.substr( -i -1, 1) + dollarFinal;
            }   

            //create Cents amount and zeros if necessary
            var centsFinal:String = String(cents);

            var missingZeros:int = decimalPlace - centsFinal.length;

            if (centsFinal.length < decimalPlace)
            {
                for (var j:int = 0; j < missingZeros; j++) 
                {
                    centsFinal += "0";
                }
            }

            var finalString:String = ""

            if (neg)
            {
                finalString = "-"+currency + dollarFinal
            } else
            {
                finalString = currency + dollarFinal
            }

            if(decimalPlace > 0)
            {
                finalString += decimalSeparator + centsFinal;
            } 

            return finalString;
        }
    }
}
Joeflash
  • 76
  • 3