← Go back

Formatting a floating-point number in Arma 3 SQF


Posted on May 04, 2018 at 11:50 (GMT +00:00) by Colin

Today, I was wanting to add a nicely formatted currency to a mod I am working on and ran into a problem..... (Arma SQF has almost no decent inbuilt handling of large numbers and has many precision problems).

I had to come up with a simple solution and while this is not the most optimal or ideal way, it works perfectly fine for most cases.


//
// Format a float-point number. e.g. 5233255.12 => 5,233,255.12
// Copyright (c) Colin J.D. Stewart. All rights reserved.
// Free for use with credit to author.
// Example: [_number, 2, ".", ","] call PX_fnc_formatNumber;
//
PX_fnc_formatNumber = {
	params ["_number", "_decimals", "_decsym", "_thsym"];
	private ["_arr", "_str", "_count"];
	
	_str = "";
	_count = 0;
	
	_arr = toArray (_number toFixed _decimals);
	reverse _arr;	
	{
		_x = toString [_x];
		
		if (_forEachIndex == _decimals) then {
			_str = _decsym + _str;
		} else {
			if (_forEachIndex < _decimals) then {
				_str = _x + _str;
			} else {
				if (_count == 3) then {
					_count = 0;
					_str = _thsym + _str;
				};
					
				_str = _x + _str;
				_count = _count + 1;			
			};
		};
	} forEach _arr;

	_str;
};


You can use this function to output different formats for different languages, but be warned that precision is quite low due to Arma 3 limitations (this is a problem for another day)

A few examples and output:


"$" + ([345435.21, 2, ".", ","] call PX_fnc_formatNumber);

//Output: $345,435.22



"$" + ([1343345435.21, 2, ".", ","] call PX_fnc_formatNumber);

//Output: $1,343,345,408.00 - notice that precision is lost


How about the Bulgarian currency (leva)?


format["%1%2",([113225.21, 2, ",", " "] call PX_fnc_formatNumber), " лв"];

//Output: 113 225,21 лв


and a sample in-use:



That's all for now, later I will take a look at solving the decimal places precision. If this was helpful or you already know a solution for the decimal places, please drop me a reply below and don't forget to leave credit where due if you use this code. Thanks!

EDIT

Due to the additional parameters the function can perform better if you plan to use it for a specific format, you can modify the function for example like so:


//
// Format a float-point number. e.g. 5233255.12 => 5,233,255.12 - faster than regular PX_fnc_formatNumber
// Copyright (c) Colin J.D. Stewart. All rights reserved.
// Free for use with credit to author.
// Example: _number call PX_fnc_formatNumberEx;
//
#define PX_DC_SEP "."
#define PX_TH_SEP ","
#define PX_DC_PL 2

PX_fnc_formatNumberEx = {
    private ["_arr", "_str", "_count"];
        
    _count = 0;
    _arr = (_this toFixed PX_DC_PL) splitString ".";
    _str = PX_DC_SEP+(_arr select 1);
    _arr = toArray(_arr select 0);
    reverse _arr;    
    
    {        
        if (_count == 3) then {
            _count = 0;
            _str = PX_TH_SEP + _str;
        };
                    
        _str = toString[_x] + _str;
        _count = _count + 1;            
    } forEach _arr;

    _str;
};


this will use 2 decimal places, "." for decimal separator and "," for thousands separator, but will perform much faster if under heavy usage.
/Scripting/Programming