Menu

Number Format

Joe Clay | Jan 10, 2018

Let's format some numbers

Often there's a need to make a ticker-style number growing from some number into another number. If you haven't had that request you haven't been working in this industry for more than five minutes. The problem is, while you can make a slider cycle through numbers from -1,000,000 to 1,000,000, you can't get those commas in there without some work. And unless you truncate the decimals you can get some really long decimal values too. Unfortunately, After Effects's available functions are sometimes limited so there's no number format function.

So I made a reasonable facsimile. Enter my number format expression. Here's what it looks like.

//Apply to SourceText
m = effect("Multiplier")("Slider");
e = Math.round(Math.log(m)/Math.log(10));
n = effect("Number")("Slider").value;
neg = n < 0 ? '-' : '';
n = Math.abs(n).toFixed(e)*m;
s = n.toString();
n = '';
for(i = s.length; i > 0; i--) {
    if((s.length-i) % 3 == 0) { n += ',' }
    n += s.charAt(i-1);
}
n = n.split('').reverse().join('');
neg + n.substr(0,n.length-1);

To use this, you need to add two sliders to your text layer. Call them Number and Multiplier. The multiplier is used to get numbers higher than one million. If you have 1234.567 as your value for example, if your multiplier is 1,000 you'll get 1,234,567 which is obviously over one million. You can enter numbers to a ton of decimal places though AE will usually only display 2-3 depending upon how you've interacted with the UI. You can also double click on a keyframe to see a slightly more precise value.

Note, I'd keep that Multiplier slider set to powers of 10—100 is 1 by the way so if you want the number to be exactly the same as the number slider without decimals, set the multiplier to 1.

How it works

m = effect("Multiplier")("Slider");
e = Math.round(Math.log(m)/Math.log(10));

First we grab our Multiplier slider. Then we see how many factors of 10 we're going to multiply by. This is necessary to truncate our Number value later on so that we don't end up with decimals or other weird formatting in our number. Even though you may only see 2 decimal places, there can be about twenty digits AE holds onto in the background.

Since there's also no Math.log10() function in AE for some reason, we have to calulate that ourselves. So we take the log of our Multiplier, and divide it by log10. We're also using Math.round()—it could also be Math.ceil() for our purposes—because sometimes Javascript math is odd. For example, taking log10 of 1000 is 2.999999999... instead of 3 for some reason and we need it to be dead on 3. This value is stored in e for exponent.

n = effect("Number")("Slider").value;
neg = n < 0 ? '-' : '';
n = Math.abs(n).toFixed(e)*m;
s = n.toString();

Next, we'll grab our Number slider. We need to add .value to the end of this one because it has to be a float and not some other type of variable. Then we do a quick check with a ternary structure so that we can conditionally set a variable in one line. If n is negative, we save - to the neg variable, otherwise it's an empty string. That will be tacked on to the front of our number later.

Then we take the absolute value of our number, since that sign—the dash—will mess us up. You could just truncate that character off, but dropping the sign with Math.abs()—taking the absolute value—should be a faster operation. Then we convert that number to a fixed string with e decimals. And that final result is multiplied by our multiplier m and saved back to n.

Even though we've converted our floating point number to a string using toFixed(), that math still works thankfully. But we need a string for what we're going to do next.

s = n.toString();
n = '';

So we convert n to a string and save it to s for, uh, string. Then we clear out n because there's no point to making another variable and n makes sense since it'll hold our number again at the end.

for(i = s.length; i > 0; i--) {
    if((s.length-i) % 3 == 0) { n += ',' }
    n += s.charAt(i-1);
}

In this for loop, we're going to loop backwards from the end of the string to the front. This will allow us to place commas every three characters. You could do this forwards, but going backwards is simpler and probably faster to execute.

So we'll start by setting i equal to the amount of characters in the string—the length—and while i is greater than zero this loop will function. Every time through the loop we'll decrement i by 1.

Each time through the loop, we'll check to see if the original string length minus the current value of i is a multiple of 3. We do that by using modulo and checking if our value is 0. If it is, we're at a third character and we'll concatenate or append a comma to the end of variable n. On the first time through this loop, the value we'll modulus will be zero so it will append a comma as the first character of string n. We'll drop that off later.

Then we append the charcter at position i-1 to the variable n. We have to subtract one because character position is zero-indexed while length is 1 indexed. For example if we have ten characters the tenth character is 9, because we start counting character position at 0.

At this point we'll be left with a number that looks like: ,987,654,321

n = n.split('').reverse().join('');
neg + n.substr(0,n.length-1);

So then we'll use split to convert our string into an array of characters, then we'll reverse that array and join it back together with an empty string. This would leave us with 123,456,789,. So in the next line we add that negative sign—if there was one—back in and then truncate off that last comma using substring.

And that's it. It took a bit of fiddling, and it's not as perfect as just having a number format function like many languages do. But it works when you need it. The only thing this won't do is decimals. If you need decimals with large numbers, it'd be easier to add another slider and deal with them separately. If I have a need for that, I'll make it and make it available. But that's unlikely. Most of the time you do that with smaller numbers so just use a simple toFixed(2) on the value from the slider and call it a day. This mainly helps for larger numbers where the specificty of decimals are less important.

This is also a Quiver file for this expression available to Patrons. It's available in the general Quiver folder. The link can be found on a prior Patreon post!

I feel like this is a good way to explore some expressions in a little more depth. If you enjoyed this format, leave a comment below, or message me on twitter @workbench_tv.