This project contains nine different language implementations of a simple algorithm named “commaize” that inserts commas into a number. The languages are: bash, c++, java, javascript, perl, php, python, ruby and tcl. My hope is that it will be a useful reference.
Contents
- Introduction
- Downloads
- Download Files
- Installation
- Bash Implementation
- C++ Implementation
- Java Implementation
- Javascript Implementation
- Perl Implementation
- PHP Implementation
- Python Implementation
- Ruby Implementation
- Tcl Implementation
- Tested Platforms
- License
Introduction
I created it because I sometimes have to work on code written in a variety of languages. Having an example like this is really helpful as a reference for languages that I rarely use (like tcl). Note that because these implementations are meant to act as a reference, they are not optimized.
This project contains the algorithm coded in complete standalone programs. Each program prints a similar list of formatted data in 3 columns. The first column is the test number, the second is the language specific format of the input and the third column is the output. That third column must be identical for all programs. In some cases there is a fourth column to remind me of what the row is for. This is what the output looks like for the python implementation (commaize.py):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
$ ./commaize.py 1 1 1 2 12 12 3 123 123 4 1234 1,234 5 12345 12,345 6 123456 123,456 7 1234567 1,234,567 8 12345678 12,345,678 9 123456789 123,456,789 10 1.23 1.23 11 12.34 12.34 12 123.45 123.45 13 1234.56 1,234.56 14 12345.67 12,345.67 15 123456.78 123,456.78 16 1234567.89 1,234,567.89 17 12345678.9 12,345,678.9 18 1.0 1 19 -1 -1 20 -12 -12 21 -123 -123 22 -1234 -1,234 23 -12345 -12,345 24 -123456 -123,456 25 -1234567 -1,234,567 26 -12345678 -12,345,678 27 -123456789 -123,456,789 28 -1.23 -1.23 29 -12.34 -12.34 30 -123.45 -123.45 31 -1234.56 -1,234.56 32 -12345.67 -12,345.67 33 -123456.78 -123,456.78 34 -1234567.89 -1,234,567.89 35 -12345678.9 -12,345,678.9 36 -1.0 -1 37 123456789 123,456,789 38 12345678,9 12.345.678,9 # EU style 39 12345.123 12,345.12 # 2 decimal places 40 12345 12,345.00 # 2 decimal places 41 12345.1251 12,345.13 # 2 decimal places 42 1234567.89 1,234,567.9 # 1 decimal place |
Note that there are two compiled languages: c++ and java so there is a Makefile that will run the compilations. You will have to edit it to pick up the correct compiler. When you do you will see that I used gcc-4.8.2 installed locally on my Mac as described here: http://joelinoff.com/blog/?p=1003 because I wanted the latest C++-11 features.
The javascript implementation requires browser rendering so it has an associated commaize.html file.
All of the source code is freely available based on the MIT license. See the LICENSE.txt file for details.
↑ Downloads
All of the implementations are available to download. There are three archive formats: tar.bz2, tar.gz and zip.
File | Size | Checksum | Extract Command |
---|---|---|---|
commaize.tar.bz2 | 13K | 60400 |
tar jxf commaize.tar.bz2
|
commaize.tar.gz | 14K | 5113 |
tar zxf commaize.tar.gz
|
commaize.zip | 21K | 54782 |
unzip commaize.zip
|
↑ Download Files
The archives contain the following files in a local commaize directory.
File | Description |
---|---|
commaize.html | HTML file that references commaize.js. |
commaize.cc | The C++ implementation. Uses some features from C++11. |
commaize.java | The java (1.6) implementation. |
commaize.js | The javascript implementation. |
commaize.pl | The perl (5.12) implementation. |
commaize.php | The php (5.4) implementation. |
commaize.py | The python (2.7) implementation. |
commaize.rb | The ruby (0.9.6, 1.8.7) implementation. |
commaize.sh | The bash implementation. |
commaize.tcl | The tcl (8.6) implementation. |
golden.txt | The golden output for testing. |
LICENSE.txt | The source code license information. |
Makefile | Builds and tests the implementations. Here are some interesting targets.
You will need to modify this file for your environment. |
README.txt | Information about the project. |
↑ Installation
The package is available in 3 formats: bzipped tar format, gzipped tar format and zip format. The following example shows how to download, install and run the project using the bzipped tar format.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
$ # Installation example. $ # There are three ways to download the project. $ wget http://projects.joelinoff.com/commaize/commaize.tar.bz2 $ wget http://projects.joelinoff.com/commaize/commaize.tar.gz $ wget http://projects.joelinoff.com/commaize/commaize.zip $ # There are three ways to extract the project. $ tar jxf commaize.tar.bz2 $ #tar zxf commaize.tar.gz $ #unzip commaize.zip $ # Here is the basic recipe but note that you MUST edit the $ # Makefile to point to the correct local c++ compiler. $ cd commaize $ edit Makefile # change the GXX compiler references $ make [output snipped] # ================================================================ # test # ================================================================ 1 test-commaize.class.out passed 2 test-commaize.exe.out passed 3 test-commaize.php.out passed 4 test-commaize.pl.out passed 5 test-commaize.py.out passed 6 test-commaize.rb.out passed 7 test-commaize.sh.out passed 8 test-commaize.tcl.out passed TOTAL: 8 PASSED: 8 FAILED: 0 |
↑ Bash Implementation
This is the bash implementation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
#!/bin/bash # # Insert thousands separator into a number and, optionally, specify # the number of decimal places. # # Here are some examples that demonstrate how it is used. # # x=$(commaize 1234) # 1,234 # x=$(commaize -1234) # -1,234 # x=$(commaize 12345.678) # 12,345.678 # x=$(commaize -12345.678) # -12,345.678 # x=$(commaize 12345.678 2) # 12,345.69 # x=$(commaize 12345.678 1) # 12,345.7 # x=$(commaize 1234 -1 ".") # 1.234 # x=$(commaize "1234567,89" -1 "." ",") # EU format: 1.234.567,89 # # The arguments are: # # $1 == number # $2 == decimal places (default: -1 -> do nothing) # $3 == thousands separator (default: ",") # $4 == decimal point (default: ".") # function commaize() { local num="$1" local dpl=-1 local sep="," local dpt="." if [[ "$2" != "" ]] ; then dpl=$2 ; fi if [[ "$3" != "" ]] ; then sep="$3" ; fi if [[ "$4" != "" ]] ; then dpt="$4" ; fi if (( $dpl >= 0 )) ; then fmt="%.${dpl}f" num=$(printf "$fmt" $num) fi local neg="" if [[ "${num:0:1}" == "-" ]] ; then neg="-" # Strip off the leading minus sign. numl=$((${#num} - 1)) num=${num:1:$numl} fi local parts=($(echo "$num" | tr "$dpt" "\n")) local nparts=${#parts[@]} if (( $nparts > 2 )) ; then echo "ERROR: invalid string: $num" exit 1 fi # Insert the separators. characteristic=${parts[0]} result='' j=$(( ${#characteristic} % 3 )) for (( i=0; i<${#characteristic}; i++ )); do k=$(( $i % 3)) if (( $k == $j )) && (( $i > 0 )) ; then result="$result$sep" fi digit={characteristic:$i:1} result="$result$digit" done # There was a decimal point, append # the mantissa. if (( $nparts == 2 )) ; then mantissa="${parts[1]}" if (( $dpl < 0 )) ; then # Strip off trailing zeros if dpl was not not specified. # Convert 1.0 --> 1 mantissa=$(echo "$mantissa" | sed -e 's/0$//g') fi if (( ${#mantissa} > 0 )) ; then result="$result$dpt$mantissa" fi fi echo "$neg$result" } # Main idx=0 data=(1 12 123 1234 12345 123456 1234567 12345678 123456789 1.23 12.34 123.45 1234.56 12345.67 123456.78 1234567.89 12345678.9 1.0 -1 -12 -123 -1234 -12345 -123456 -1234567 -12345678 -123456789 -1.23 -12.34 -123.45 -1234.56 -12345.67 -123456.78 -1234567.89 -12345678.9 -1.0 '123456789') for datum in ${data[@]}; do result=$(commaize $datum) idx=$(($idx + 1)) printf "%4d %20s %20s\n" $idx $datum $result done datum="12345678,9" result=$(commaize $datum -1 '.' ',') idx=$(($idx + 1)) printf "%4d %20s %20s # EU style\n" $idx $datum $result data=(12345.123 12345 12345.1251) for datum in ${data[@]}; do result=$(commaize $datum 2) idx=$(($idx + 1)) printf "%4d %20s %20s # 2 decimal places\n" $idx $datum $result done datum=1234567.89 result=$(commaize $datum 1) idx=$(($idx + 1)) printf "%4d %20s %20s # 1 decimal place\n" $idx $datum $result |
↑ C++ Implementation
This is the C++ implementation. It uses C++-11 constructs so it will not work on platforms that do not have a recent C++ compiler. In my case I had to install an updated version of the C++ compiler to handle C++-11 constructs from http://joelinoff.com/blog/?p=1003.
This is how I compiled it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
$ # First install the compiler. The default is too old. $ # You can skip this step if you have newer version. $ cd ~/work $ mkdir -p gcc/4.8.2 $ cd gcc/4.8.2 $ wget http://projects.joelinoff.com/gcc-4.8.2./Makefile <output snipped> $ wget http://projects.joelinoff.com/gcc-4.8.2./bld.sh <output snipped> $ make <output snipped> $ # Now compile your program. $ cd ~/work/commaize $ CXX_RTFDIR=~/work/gcc/4.8.2/rtf $ export PATH="${CXX_RTFDIR}/bin:${PATH}" $ export LD_LIBRARY_PATH="$(CXX_RTFDIR)/lib:$(CXX_RTFDIR)/lib64:${LD_LIBRARY_PATH}" $ export LD_RUN_PATH="${CXX_RTFDIR}/lib:${CXX_RTFDIR}/lib64:${LD_LIBRARY_PATH}" $ g++ --version # make sure that you have the correct version <output snipped> $ g++ -g -Wall -std=c++11 -o commaize.exe commaize.cc <output snipped> $ # Run it. $ ./commaize.exe <output snipped> |
This is the source code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
// ================================================================ // Commaize a number. // ================================================================ #include <cstdlib> #include <string> #include <iostream> #include <iomanip> using namespace std; template <typename T> string commaize_tostring(T in) {return to_string(in);} string commaize_tostring(const string& in) {return in;} /** * Insert thousands separator into a number and, optionally, specify * the number of decimal places. * * Here are some examples that demonstrate how it is used. * * string x; * x=commaize(1234) # 1,234 * x=commaize(-1234) # -1,234 * x=commaize(12345.678) # 12,345.678 * x=commaize(-12345.678) # -12,345.678 * x=commaize(12345.678, dpl=2) # 12,345.69 * x=commaize(12345.678, dpl=1) # 12,345.7 * x=commaize(1234,sep='.') # 1.234 * x=commaize("1234567,89", sep='.', dpt=',') # EU: 1.234.567,89 * * The arguments are: * * @param num The number: int, float or string. * @param dpl Decimal places (default: -1 -> do nothing). * @param sep Thousands separator (default: ","). * @param dpt Decimal point (default: "."). * @returns a formatted string. */ template <typename T> string commaize(T num, int dpl=-1, char sep=',', char dpt='.') { string characteristic = commaize_tostring(num); if (dpl >= 0) { // Use sprintf() to do the rounding. double val = atof(characteristic.c_str()); char fmt[128]; char tmp[128]; sprintf(fmt, "%%.%df", dpl); sprintf(tmp, fmt, val); characteristic = tmp; } string neg=""; if (characteristic[0] == '-') { neg = "-"; characteristic = characteristic.substr(1, string::npos); } string mantissa = ""; size_t pos = characteristic.find(dpt); if (pos != string::npos) { // There is a decimal point, break out // the characteristic and the mantissa // because we only care about the // characteristic for commas. We will // append the mantissa at the end. mantissa = characteristic.substr(pos+1); // Trim trailing zeros. if (dpl < 0) { while (mantissa.size() > 0 && mantissa[mantissa.size()-1] == '0') { mantissa = mantissa.substr(0, mantissa.size() - 1); } } characteristic = characteristic.substr(0, pos); } // Insert the commas. size_t j = characteristic.size() % 3; string result = ""; result.reserve(characteristic.size() + ((characteristic.size()/3) + 2 + mantissa.size())); for(size_t i=0; i<characteristic.size(); i++) { if ((i%3) == j && i > 0) { result += sep; } result += characteristic[i]; } if (!mantissa.empty()) { char dpts[2] = {dpt, 0}; result += string(dpts) + mantissa; } return neg + result; } /** * main */ int main() { string result; string str; unsigned id = 0; // Test positive integers. size_t nums[] = {1, 12, 123, 1234, 12345, 123456, 1234567, 12345678, 123456789}; for(auto num : nums) { result = commaize(num); cout << setw(4) << right << ++id << " " << right << setw(20) << num << " " << right << setw(20) << result << endl; } // Test positive doubles. double dnums[] = {1.23, 12.34, 123.45, 1234.56, 12345.67, 123456.78, 1234567.89, 12345678.9, 1.0}; for(auto dnum : dnums) { result = commaize(dnum); cout << setw(4) << right << ++id << " " << right << fixed << setw(20) << dnum << " " << right << setw(20) << result << endl; } // Test negative integers. for(long num: nums) { num = -num; result = commaize(num); cout << setw(4) << right << ++id << " " << right << setw(20) << num << " " << right << setw(20) << result << endl; } // Test negative doubles. for(auto num: dnums) { num = -num; result = commaize(num); cout << setw(4) << right << ++id << " " << right << fixed << setprecision(2) << setw(20) << num << " " << right << setw(20) << result << endl; } // String test. str = "123456789"; result = commaize(str); cout << setw(4) << right << ++id << " " << right << setw(20) << str << " " << right << setw(20) << result << endl; // EU style str = "12345678,9"; result = commaize(str, -1, '.', ','); cout << setw(4) << right << ++id << " " << right << fixed << setprecision(2) << setw(20) << str << " " << right << setw(20) << result << " # EU style" << endl; // dollarize // Round to 2 significant digits. double ddata[] = {12345.123, 12345, 12345.1251}; for(auto datum : ddata) { result = commaize(datum, 2); cout << setw(4) << right << ++id << " " << right << fixed << setw(20) << datum << " " << right << setw(20) << result << " # 2 decimal places" << endl; } // 1 decimal place. string datum = "1234567.89"; result = commaize(datum, 1); cout << setw(4) << right << ++id << " " << right << fixed << setw(20) << datum << " " << right << setw(20) << result << " # 1 decimal place" << endl; } |
↑ Java Implementation
This is the java implementation. You compile it as follows:
1 2 3 4 |
$ javac Commaize.java <output snipped> $ java Commaize <output snipped> |
Here is the source code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
// Commaize a number. import java.util.*; public class Commaize { /** * doubleToString */ public static String doubleToString(double in) { Double d = in; int di = d.intValue(); if (d == di) { // Optimization for easy floats. return String.format("%d", di); } String floatnum = String.format("%f", d); // Chop off trailing zeros. int i = floatnum.length() - 1; while (i >= 0 && floatnum.charAt(i) == '0') { i--; } floatnum = floatnum.substring(0, i+1); // Chop off the period if there is no mantissa. i = floatnum.length() - 1; if (i >= 0 && floatnum.charAt(i) == '.') { floatnum = floatnum.substring(0, i); } return floatnum; } /** * Insert thousands separator into a number and, optionally, specify * the number of decimal places. * * Here are some examples that demonstrate how it is used. * * string x; * x=commaize(1234) # 1,234 * x=commaize(-1234) # -1,234 * x=commaize(12345.678) # 12,345.678 * x=commaize(-12345.678) # -12,345.678 * x=commaize(12345.678, 2) # 12,345.69 * x=commaize(12345.678, 1) # 12,345.7 * x=commaize(1234, -1, '.') # 1.234 * x=commaize("1234567,89", -1, '.', ',') # EU: 1.234.567,89 * * The arguments are: * * @param num The number: int, float or string. * @param dpl Decimal places (default: -1 -> do nothing). * @param sep Thousands separator (default: ","). * @param dpt Decimal point (default: "."). * @returns a formatted string. */ public static <T> String commaize(T num, int dpl, char sep, char dpt) { String rep = num.toString(); if (rep.indexOf('E') >= 0) { rep = doubleToString(Double.parseDouble(rep)); } if (dpl > 0) { // Take advantage of built in rounding. String fmt = String.format("%%.%df", dpl); double value = Double.parseDouble(rep); rep = String.format(fmt, value); } // Get the parts of the number (characteristic and mantissa). // 123.45 // ^ ^^ // | |+--- mantissa // | +---- decimal point // +------- characteristic String characteristic = ""; String mantissa = ""; boolean past_dpt = true; for (int i=0; i<rep.length(); i++) { char ch = rep.charAt(i); if (ch == dpt) { past_dpt = false; } if (past_dpt) { characteristic += ch; } else { mantissa += ch; } } // Trim trailing zeros. if (dpl < 0) { int i = mantissa.length() - 1; while (i >= 0 && mantissa.charAt(i) == '0') { i--; } mantissa = mantissa.substring(0, i+1); i = mantissa.length() - 1; if (i >= 0 && mantissa.charAt(i) == dpt) { // Eliminate the decimal point separater if there are no // trailing values (e.g. "1."). mantissa = ""; } } // Handle negative numbers. String neg = ""; if (characteristic.charAt(0) == '-') { neg = "-"; characteristic = characteristic.substring(1); } // Insert the command moving from left to right. String result = ""; int offset = characteristic.length() % 3; // offset to first comma for(int i=0; i<characteristic.length(); i++) { if (((i%3) == offset) && (i > 0)) { result += sep; } result += characteristic.charAt(i); } rep = neg + result + mantissa; return rep; } public static <T> String commaize(T num) { return commaize(num, -1, ',', '.'); } public static <T> String commaize(T num, int dpl) { return commaize(num, dpl, ',', '.'); } /** * main. */ public static void main(String[] args) { int id = 0; String result; String str; String msg; // Test positive integers. int inums[] = new int[] {1, 12, 123, 1234, 12345, 123456, 1234567, 12345678, 123456789}; for(int val : inums) { result = commaize(val); msg = String.format("%4d %20d %20s", ++id, val, result); System.out.println(msg); } // Test positive floating points. double dnums[] = new double[] {1.23, 12.34, 123.45, 1234.56, 12345.67, 123456.78, 1234567.89, 12345678.9, 1.0}; for(double val : dnums) { str = doubleToString(val); result = commaize(val); msg = String.format("%4d %20s %20s", ++id, str, result); System.out.println(msg); } // Test negative integers. for(int val : inums) { int nval = -val; result = commaize(nval); msg = String.format("%4d %20d %20s", ++id, nval, result); System.out.println(msg); } // Test negative floating points. for(double val : dnums) { double nval = -val; result = commaize(nval); str = doubleToString(nval); msg = String.format("%4d %20s %20s", ++id, str, result); System.out.println(msg); } // String test. str = "123456789"; result = commaize(str); msg = String.format("%4d %20s %20s", ++id, str, result); System.out.println(msg); // EU style str = "12345678,9"; result = commaize(str, -1, '.', ','); msg = String.format("%4d %20s %20s", ++id, str, result); System.out.println(msg); // dollarize // Round to 2 significant digits. double ddata[] = new double[] {12345.123, 12345, 12345.1251}; for(double val : ddata) { str = doubleToString(val); result = commaize(val, 2); msg = String.format("%4d %20s %20s", ++id, str, result); System.out.println(msg); } // 1 decimal place str = "1234567.89"; result = commaize(str, 1); msg = String.format("%4d %20s %20s", ++id, str, result); System.out.println(msg); } } |
↑ Javascript Implementation
This is the javascript implementation. It consists of two parts: an HTML wrapper and the javascript code. You can run it in your browser by navigating to the HTML page or you can use a local javascript testing environment like rhino.
When you run it in your browser the output looks like this:
Here is the HTML source code.
1 2 3 4 5 6 7 8 9 10 11 |
<!DOCTYPE HTML> <html> <head> <title>commaize</title> <script type="text/javascript" src="commaize.js"></script> </head> <body> <div id="place"> </div> </body> </html> |
Here is the javascript source code. Note that this implementation deliberately avoids the use of libraries like jquery. For a production system you definitely want to use javascript libraries to make your code easier to read and more maintainable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
// This is raw javascript on purpose. window.onload = function() { // I would normally recommend using jquery ready() but since I // want to keep this example as simple as possible, jquery is // assumed to not be available. // ================================================================ // Test a condition and report a message. // ================================================================ function assert(condition, description) { if(!condition) { alert('ASSERTION: ' + description + ': ' + condition); } } // ================================================================ // Commaize a number. // Insert thousands separator into a number and, optionally, specify // the number of decimal places. // // Here are some examples that demonstrate how it is used. // // x=commaize(1234) # 1,234 // x=commaize(-1234) # -1,234 // x=commaize(12345.678) # 12,345.678 // x=commaize(-12345.678) # -12,345.678 // x=commaize(12345.678, 2) # 12,345.69 // x=commaize(12345.678, 1) # 12,345.7 // x=commaize(1234, -1, '.') # 1.234 // x=commaize("1234567,89", -1, '.', ',') # EU: 1.234.567,89 // // The arguments are: // // @param num The number: int, float or string. // @param dpl Decimal places (default: -1 -> do nothing). // @param sep Thousands separator (default: ","). // @param dpt Decimal point (default: "."). // @returns a formatted string. // ================================================================ function commaize(num, dpl=-1, sep=',', dpt='.') { var snum = num.toString(); assert(snum.indexOf(sep) < 0, 'found "' + sep + '" in "' + snum + '"'); // Format to N decimal places. if (dpl > 0) { snum = parseFloat(snum).toFixed(dpl).toString(); } // Split into parts. var parts = snum.split(dpt); // 123 or 123.45 assert( parts.length < 3, 'too many parts: ' + parts.length); // Get the characteristic and mantissa. // 123.45 // ^ ^^ // | |+--- mantissa // | +---- decimal point // +------- characteristic var characteristic = parts[0]; var mantissa = parts.length == 1 ? '' : dpt + parts[1]; // Handle negative numbers. var neg = ''; if (characteristic[0] == '-') { neg = '-'; characteristic = characteristic.slice(1); // strip off the negative } // Clean up the mantissa. Remove trailing zeros unless a specific // number of decimal places (dpl) was specified. // 1.000 > 1 if (mantissa.length && dpl < 0) { // Make sure that 1.0 --> 1 while (mantissa.slice(-1) == '0') { mantissa = mantissa.slice(0, -1); } if (mantissa == dpt) { mantissa = ""; } } // Insert the commas moving from left to right. var result = ''; // where to put the result var offset = characteristic.length % 3 // offset to start inserting commas for(var i=0; i<characteristic.length; i++) { if ((i%3) == offset && i) { // if we are at the digit where a separator needs to be // pre-pended, prepend the separator. result += sep ; } result += characteristic[i]; } return neg + result + mantissa; } // ================================================================ // main // ================================================================ function main() { // This function will generate a table on the page with the // filled in contents of the commaize function for the examples // that we are interested in. var rowidx = 0; row = function(val, result, msg='') { var s1 = "" + rowidx; var s2 = "" + val; var s3 = "" + result; var html = ''; rowidx++; // Pad. while (s1.length < 4) {s1 = ' ' + s1;} while (s2.length < 20) {s2 = ' ' + s2;} while (s3.length < 20) {s3 = ' ' + s3;} html += s1 + ' ' + s2 + ' ' + s3; if (msg.length > 0) { html += ' ' + msg; } html += '\n'; return html; } var place = document.getElementById('place'); var html = ''; html += '<pre>\n'; html += 'BEGIN\n'; // Rows of data here. var data = [1, 12, 123, 1234, 12345, 123456, 1234567, 12345678, 123456789, 1.23, 12.34, 123.45, 1234.56, 12345.67, 123456.78, 1234567.89, 12345678.9, 1.0, -1, -12, -123, -1234, -12345, -123456, -1234567, -12345678, -123456789, -1.23, -12.34, -123.45, -1234.56, -12345.67, -123456.78, -1234567.89, -12345678.9, -1.0, '123456789', ]; for(var i=0; i<data.length; i++) { var datum = data[i]; var result = commaize(datum); html += row(datum, result); } // EU style var datum = "12345678,9"; var result = commaize(datum, -1, '.', ','); // EU style html += row(datum, result, '# EU style'); // dollarize // Round to 2 significant digits. var data1 = [12345.123, 12345, 12345.1251,]; for(var i=0; i<data1.length; i++) { datum = data1[i]; result = commaize(datum, 2); html += row(datum, result, '# 2 decimal places'); } // 1 decimal place datum = "1234567.89"; result = commaize(datum, 1) html += row(datum, result, '# 1 decimal place'); html += 'END\n'; html += '</pre>\n'; place.innerHTML = html; } main(); } |
↑ Perl Implementation
This is the perl implementation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
#!/usr/bin/env perl # # Example that shows how to insert commas into a number. # use strict; use warnings; &main; # ================================================================ # main # ================================================================ sub main { my @data = (1, 12, 123, 1234, 12345, 123456, 1234567, 12345678, 123456789, 1.23, 12.34, 123.45, 1234.56, 12345.67, 123456.78, 1234567.89, 12345678.9, 1.0, -1, -12, -123, -1234, -12345, -123456, -1234567, -12345678, -123456789, -1.23, -12.34, -123.45, -1234.56, -12345.67, -123456.78, -1234567.89, -12345678.9, -1.0, '123456789', ); my $idx = 1; foreach my $datum (@data) { my $result = &commaize($datum); printf("%4d %20s %20s\n", $idx++, $datum, $result); } # EU style my $datum = "12345678,9"; my $result = &commaize($datum, -1, ".", ","); # EU style printf("%4d %20s %20s # EU style\n", $idx++, $datum, $result); # dollarize # Round to 2 significant digits. my @ddata = (12345.123, 12345, 12345.1251,); for $datum (@ddata) { $result = &commaize($datum, 2); printf("%4d %20s %20s # 2 decimal places\n", $idx++, $datum, $result); } # 1 decimal place $datum = "1234567.89"; $result = &commaize($datum, 1); printf("%4d %20s %20s # 1 decimal place\n",$idx++, $datum, $result); } # ================================================================ # Insert thousands separator into a number and, optionally, specify # the number of decimal places. # # Here are some examples that demonstrate how it is used. # # x=commaize(1234) # 1,234 # x=commaize(-1234) # -1,234 # x=commaize(12345.678) # 12,345.678 # x=commaize(-12345.678) # -12,345.678 # x=commaize(12345.678, 2) # 12,345.69 # x=commaize(12345.678, 1) # 12,345.7 # x=commaize(1234, -1, ".") # 1.234 # x=commaize("1234567,89", -1, ".", ",") # EU: 1.234.567,89 # # The arguments are: # # @param num The number: int, float or string. # @param dpl Decimal places (default: -1 -> do nothing). # @param sep Thousands separator (default: ","). # @param dpt Decimal point (default: "."). # @returns a formatted string. # ================================================================ sub commaize { my $num = shift; my $dpl = shift; my $sep = shift; my $dpt = shift; $dpl = -1 if( !defined($dpl) ); $sep = "," if( !defined($sep) ); $dpt = "." if( !defined($dpt) ); # Format to N decimal places. my $rep = $num; if ($dpl >= 0) { my $fmt = "%.${dpl}f"; $rep = sprintf($fmt, $num); } # Split into parts. # Using split is tricky here because the split value is unknown, # i work around that using this simple brute force approach. my @parts = (); my @chars = split(//, $rep); my $idx = 0; for my $char (@chars) { if ($char eq $dpt) { $idx++; } else { if ($#parts <= $idx) { push(@parts, ""); } $parts[$idx] .= $char; } } # Get the characteristic and mantissa. # 123.45 # ^ ^^ # | |+--- mantissa # | +---- decimal point # +------- characteristic my $characteristic = $parts[0]; my $mantissa = ""; $mantissa = "$dpt$parts[1]" if $#parts > 1; # Handle negative numbers. my $neg = ""; if (substr($characteristic, 0, 1) eq "-") { $neg = "-"; $characteristic = substr($characteristic, 1); } # Insert the commas moving from left to right. my $result = ""; # where to put the result my $offset = length($characteristic) % 3; # offset to start inserting commas for(my $i=0; $i<length($characteristic); $i++) { if (($i % 3) == $offset && $i) { $result .= $sep; } $result .= substr($characteristic, $i, 1); } my $final = $neg . $result . $mantissa; return $final; } |
↑ PHP Implementation
This is the PHP implementation. This is how you run it.
1 |
$ php -f commaize.php |
This is the source code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
<?php # # Example that shows how to insert commas into a number. # # ================================================================ # Insert thousands separator into a number and, optionally, specify # the number of decimal places. # # Here are some examples that demonstrate how it is used. # # x=commaize(1234) # 1,234 # x=commaize(-1234) # -1,234 # x=commaize(12345.678) # 12,345.678 # x=commaize(-12345.678) # -12,345.678 # x=commaize(12345.678, 2) # 12,345.69 # x=commaize(12345.678, 1) # 12,345.7 # x=commaize(1234, -1, ".") # 1.234 # x=commaize("1234567,89", -1, ".", ",") # EU: 1.234.567,89 # # The arguments are: # # @param num The number: int, float or string. # @param dpl Decimal places (default: -1 -> do nothing). # @param sep Thousands separator (default: ","). # @param dpt Decimal point (default: "."). # @returns a formatted string. # ================================================================ function commaize($num, $dpl=-1, $sep=",", $dpt=".") { $rep = $num; # Format to N decimal places. if ($dpl >= 0) { $fmt = "%.${dpl}f"; $rep = sprintf($fmt, $num); } # Split into parts. $parts = explode($dpt, $rep); # Get the characteristic and mantissa. # 123.45 # ^ ^^ # | |+--- mantissa # | +---- decimal point # +------- characteristic $characteristic = $parts[0]; $mantissa = count($parts) == 1 ? "" : $dpt . $parts[1]; # Handle negative numbers. $neg = ""; if ($characteristic[0] == "-") { $neg = "-"; $characteristic = substr($characteristic, 1); } # Clean up the mantissa. Remove trailing zeros unless a specific # number of decimal places (dpl) was specified. # 1.000 > 1 if (strlen($mantissa) and $dpl < 0) { # Make sure that 1.0 --> 1 $mantissa = rtrim($mantissa, "0"); $mantissa = rtrim($mantissa, $dpt); } # Insert the commas moving from left to right. $result = ""; # where to put the result $offset = strlen($characteristic) % 3; # offset to start inserting commas for($i=0; $i<strlen($characteristic); $i++) { if (($i%3) == $offset and $i > 0) { $result .= $sep; } $result .= $characteristic[$i]; } $final = $neg . $result . $mantissa; return $final; } # ================================================================ # main # ================================================================ function main() { $data = array (1, 12, 123, 1234, 12345, 123456, 1234567, 12345678, 123456789, 1.23, 12.34, 123.45, 1234.56, 12345.67, 123456.78, 1234567.89, 12345678.9, 1.0, -1, -12, -123, -1234, -12345, -123456, -1234567, -12345678, -123456789, -1.23, -12.34, -123.45, -1234.56, -12345.67, -123456.78, -1234567.89, -12345678.9, -1.0, '123456789', ); $idx = 1; foreach($data as $datum) { $result = commaize($datum); echo sprintf("%4d %20s %20s\n", $idx++, "$datum", $result); } # EU style $datum = "12345678,9"; $result = commaize($datum, -1, ".", ","); echo sprintf("%4d %20s %20s # EU style\n", $idx++, "$datum", $result); # dollarize # Round to 2 significant digits. $data = array(12345.123, 12345, 12345.1251,); foreach($data as $datum) { $result = commaize($datum, 2); echo sprintf("%4d %20s %20s # 2 decimal places\n", $idx++, "$datum", $result); } # 1 decimal place $datum = "1234567.89"; $result = commaize($datum, 1); echo sprintf("%4d %20s %20s # 1 decimal place\n", $idx++, "$datum", $result); } main(); ?> |
↑ Python Implementation
This is the python implementation. Note that I use asserts because they are available natively.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
#!/usr/bin/env python ''' Example that shows how to insert commas into a number. ''' import re def commaize(num, dpl=-1, sep=',', dpt='.'): ''' Insert thousands separator into a number and, optionally, specify the number of decimal places. Here are some examples that demonstrate how it is used. x=commaize(1234) # 1,234 x=commaize(-1234) # -1,234 x=commaize(12345.678) # 12,345.678 x=commaize(-12345.678) # -12,345.678 x=commaize(12345.678, dpl=2) # 12,345.69 x=commaize(12345.678, dpl=1) # 12,345.7 x=commaize(1234,sep='.') # 1.234 x=commaize("1234567,89", sep='.', dpt=',') # EU: 1.234.567,89 The arguments are: @param num The number: int, float or string. @param dpl Decimal places (default: -1 -> do nothing). @param sep Thousands separator (default: ","). @param dpt Decimal point (default: "."). @returns a formatted string. ''' rep = str(num) # convert the int or float number to a string assert rep.find(sep) < 0 # no separators allowed # Format to N decimal places. if dpl >= 0: fmt = '%.' + str(dpl) + 'f' rep = fmt % (float(num)) # Split into parts. parts = rep.split(dpt) # 123 or 123.45 assert len(parts) < 3 # multiple dpts not allowed # Get the characteristic and mantissa. # 123.45 # ^ ^^ # | |+--- mantissa # | +---- decimal point # +------- characteristic characteristic = parts[0] mantissa = "" if len(parts) == 1 else dpt + parts[1] # Handle negative numbers. neg = '' if characteristic[0] == '-': neg = '-' characteristic = characteristic[1:] # strip off the negative # Check our assumption that both the characteristic and the mantissa # are integers at this point. assert re.match(r'^\d+$', characteristic) # empty strings are not allowed if len(mantissa): # empty strings are allowed assert re.match(r'^' + dpt + '\d+$', mantissa) # Clean up the mantissa. Remove trailing zeros unless a specific # number of decimal places (dpl) was specified. # 1.000 > 1 if len(mantissa) and dpl < 0: # Make sure that 1.0 --> 1 mantissa = mantissa.rstrip('0') mantissa = mantissa.rstrip(dpt) # Insert the commas moving from left to right. result = '' # where to put the result offset = len(characteristic) % 3 # offset to start inserting commas for i in range(len(characteristic)): if (i%3) == offset and i: # if we are at the digit where a separator needs to be # pre-pended, prepend the separator. result += sep result += characteristic[i] final = neg + result + mantissa return final def main(): ''' Test the method. ''' idx = [0] def incidx(): idx[0] += 1 return idx[0] data = [1, 12, 123, 1234, 12345, 123456, 1234567, 12345678, 123456789, 1.23, 12.34, 123.45, 1234.56, 12345.67, 123456.78, 1234567.89, 12345678.9, 1.0, -1, -12, -123, -1234, -12345, -123456, -1234567, -12345678, -123456789, -1.23, -12.34, -123.45, -1234.56, -12345.67, -123456.78, -1234567.89, -12345678.9, -1.0, '123456789', ] for datum in data: result = commaize(datum) print('%4d %20s %20s' % (incidx(), str(datum), result)) # EU style datum = "12345678,9" result = commaize(datum, sep='.', dpt=',') # EU style print('%4d %20s %20s # EU style' % (incidx(), str(datum), result)) # dollarize # Round to 2 significant digits. data = [12345.123, 12345, 12345.1251,] for datum in data: result = commaize(datum, dpl=2) print('%4d %20s %20s # 2 decimal places' % (incidx(), str(datum), result)) # 1 decimal place datum = "1234567.89" result = commaize(datum, dpl=1) print('%4d %20s %20s # 1 decimal place' % (incidx(), str(datum), result)) if __name__ == '__main__': main() |
↑ Ruby Implementation
This is the ruby implementation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
#!/usr/bin/env ruby # ================================================================ # Insert thousands separator into a number and, optionally, specify # the number of decimal places. # # Here are some examples that demonstrate how it is used. # # x=commaize(1234) # 1,234 # x=commaize(-1234) # -1,234 # x=commaize(12345.678) # 12,345.678 # x=commaize(-12345.678) # -12,345.678 # x=commaize(12345.678, 2) # 12,345.69 # x=commaize(12345.678, 1) # 12,345.7 # x=commaize(1234, -1, '.') # 1.234 # x=commaize("1234567,89", -1, '.', ',') # EU: 1.234.567,89 # # The arguments are: # # @param num The number: int, float or string. # @param dpl Decimal places (default: -1 -> do nothing). # @param sep Thousands separator (default: ","). # @param dpt Decimal point (default: "."). # @returns a formatted string. # ================================================================ def commaize(num, dpl=-1, sep=',', dpt='.') snum = num.to_s raise "invalid number format" unless snum.count(sep.to_s) == 0 # Format to N decimal places. if (dpl >= 0) then fmt = '%.' << dpl.to_i.to_s << 'f' snum = sprintf fmt, snum.to_f end # Split into parts. parts = snum.split(dpt) raise "invalid number of parts: %d" % (parts.length) unless parts.length < 3 # Get the characteristic and mantissa. # 123.45 # ^ ^^ # | |+--- mantissa # | +---- decimal point # +------- characteristic characteristic = parts[0] mantissa = parts.length > 1 ? dpt + parts[1] : "" # Handle negative numbers. neg = "" if (characteristic[0] == '-') characteristic = characteristic[1..-1] neg = "-" end # Clean up the mantissa. Remove trailing zeros unless a specific # number of decimal places (dpl) was specified. # 1.000 > 1 if (mantissa.length > 0 and dpl < 0) then # Make sure that 1.0 --> 1 while (mantissa[-1] == '0') mantissa = mantissa.chomp("0") end mantissa = mantissa.chomp(dpt) end # Insert the commas moving from left to right. result = "" j = characteristic.length % 3 characteristic.split("").each_with_index do |item, i| if ((i%3) == j and i > 0) then # if we are at the digit where a separator needs to be # pre-pended, prepend the separator. result << sep end result << item end if (mantissa.length) then result << mantissa end return neg + result end # ================================================================ # Test method. # ================================================================ def test() data = [1, 12, 123, 1234, 12345, 123456, 1234567, 12345678, 123456789, 1.23, 12.34, 123.45, 1234.56, 12345.67, 123456.78, 1234567.89, 12345678.9, 1.0, -1, -12, -123, -1234, -12345, -123456, -1234567, -12345678, -123456789, -1.23, -12.34, -123.45, -1234.56, -12345.67, -123456.78, -1234567.89, -12345678.9, -1.0, '123456789', ] idx = 1 incidx = lambda do idx += 1 return idx end data.each do |num| result = commaize(num) print("%4d %20s %20s\n" % [incidx.call(), num.to_s, result]) end # EU style datum = "12345678,9" result = commaize(datum, -1, '.', ',') # EU style print("%4d %20s %20s # EU style\n" % [incidx.call(), datum.to_s, result]) # dollarize # Round to 2 significant digits. data = [12345.123, 12345, 12345.1251,] data.each do |num| result = commaize(num, 2) print("%4d %20s %20s # 2 decimal places\n" % [incidx.call(), num.to_s, result]) end # 1 decimal place datum = "1234567.89" result = commaize(datum, dpl=1) print("%4d %20s %20s # 1 decimal place\n" % [incidx.call(), datum.to_s, result]) end if __FILE__ == $0 test() end |
↑ Tcl Implementation
This is the tcl implementation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
#!/usr/bin/env tclsh # # Example that shows how to insert commas into a number. # # ================================================================ # Insert thousands separator into a number and, optionally, specify # the number of decimal places. # # Here are some examples that demonstrate how it is used. # # set x [commaize 1234] # 1,234 # set x [commaize -1234] # -1,234 # set x [commaize 12345.678] # 12,345.678 # set x [commaize -12345.678] # -12,345.678 # set x [commaize 12345.678 2] # 12,345.69 # set x [commaize 12345.678 1] # 12,345.7 # set x [commaize 1234 -1 "."] # 1.234 # set x [commaize "1234567,89" "." ","] # EU: 1.234.567,89 # # The arguments are: # # @param num The number: int, float or string. # @param dpl Decimal places (default: -1 -> do nothing). # @param sep Thousands separator (default: ","). # @param dpt Decimal point (default: "."). # @returns a formatted string. # ================================================================ proc commaize {num {dpl -1} {sep ","} {dpt "."}} { set rep $num # Format to N decimal places. if {$dpl >= 0} { set fmt "%.${dpl}f" set rep [format $fmt $num] } # Split into parts. set parts [split $rep $dpt] set size [llength $parts] # Get the characteristic and mantissa. # 123.45 # ^ ^^ # | |+--- mantissa # | +---- decimal point # +------- characteristic set characteristic [lindex $parts 0] if {$size == 1} { set mantissa "" } else { set num [lindex $parts 1] set mantissa "${dpt}${num}" } # Trim off trailing zeros. if {$dpl < 0} { set mantissa [string trimright $mantissa "0"] set mantissa [string trimright $mantissa $dpt] } # Handle negative numbers. set neg [string index $characteristic 0] if {[string compare $neg "-"] == 0} { # strip off the negative set characteristic [string range $characteristic 1 [string length $characteristic]] } else { set neg "" } # Insert the commas moving from left to right. set result "" set offset [expr [string length $characteristic] % 3] for {set i 0} {$i < [string length $characteristic]} {incr i} { if {[expr $i>0] && [expr ($i%3)] == $offset} { append result $sep } append result [string index $characteristic $i] } set final "${neg}{result}${mantissa}" return $final } # ================================================================ # main # ================================================================ proc main {} { set data [list 1 12 123 1234 12345 123456 1234567 12345678 123456789 \ 1.23 12.34 123.45 1234.56 12345.67 123456.78 1234567.89 12345678.9 \ 1.0 \ -1 -12 -123 -1234 -12345 -123456 -1234567 -12345678 -123456789 \ -1.23 -12.34 -123.45 -1234.56 -12345.67 -123456.78 -1234567.89 -12345678.9 \ -1.0 \ "123456789" \ ] set idx 0 foreach datum $data { incr idx set result [commaize $datum] set f [format "%4d %20s %20s" $idx $datum $result] puts $f } # EU style set datum "12345678,9" incr idx set result [commaize $datum -1 "." ","] set f [format "%4d %20s %20s" $idx $datum $result] puts $f # dollarize # Round to 2 significant digits set data [list 12345.123 12345 12345.1251] foreach datum $data { incr idx set result [commaize $datum 2] set f [format "%4d %20s %20s" $idx $datum $result] puts $f } # 1 decimal place set datum "1234567.89" incr idx set result [commaize $datum 1] set f [format "%4d %20s %20s" $idx $datum $result] puts $f } main |
↑ Tested Platforms
I have tested this on the following platforms. In all cases I had to install an updated versions of the C++ compiler to handle C++-11 constructs from http://joelinoff.com/blog/?p=1003.
Platform | Status> | Notes |
---|---|---|
CentOS 5.5 | Passed | Required installion of g++ 4.8.2 |
CentOS 5.8 | Passed | Required installation of g++ 4.8.2 |
CentOS 6.5 | Passed | Required installation of g++ 4.8.2 |
Mac OS X 10.9.2 | Passed | Required installation of g++ 4.8.2 |
↑ License
This software is licensed under the MIT open source license.
Copyright (c) 2014 by Joe Linoff
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Enjoy!