├── .npmrc
├── .gitignore
├── wrapEach.tmpl
├── src
├── maxSafeInteger.js
├── index.js
├── isSafeNumber.js
├── isFinite.js
├── toWordsOrdinal.js
├── toOrdinal.js
├── makeOrdinal.js
└── toWords.js
├── .prettierrc
├── spec
├── support
│ └── jasmine.json
├── indexSpec.js
├── index.html
├── isSafeNumberSpec.js
├── toOrdinalSpec.js
├── toWordsOrdinalSpec.js
├── phantom
│ └── run-jasmine3.js
└── toWordsSpec.js
├── ROADMAP.md
├── .eslintrc
├── .editorconfig
├── wrapBundle.tmpl
├── LICENSE
├── bower.json
├── gulpfile.js
├── package.json
├── numberToWords.min.js
├── README.md
└── numberToWords.js
/.npmrc:
--------------------------------------------------------------------------------
1 | save-exact = true
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .idea
3 | node_modules
4 | notes.md
5 |
--------------------------------------------------------------------------------
/wrapEach.tmpl:
--------------------------------------------------------------------------------
1 | // ========== file: <%= file.path.replace(file.cwd, '') %> ==========
2 | <%= file.contents %>
--------------------------------------------------------------------------------
/src/maxSafeInteger.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var MAX_SAFE_INTEGER = 9007199254740991;
4 |
5 | module.exports = MAX_SAFE_INTEGER;
6 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "arrowParens": "avoid",
3 | "singleQuote": true,
4 | "tabWidth": 4,
5 | "trailingComma": "none"
6 | }
7 |
--------------------------------------------------------------------------------
/spec/support/jasmine.json:
--------------------------------------------------------------------------------
1 | {
2 | "spec_dir": "spec",
3 | "spec_files": [
4 | "**/*[sS]pec.js"
5 | ],
6 | "helpers": [
7 | "helpers/**/*.js"
8 | ]
9 | }
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | toOrdinal: require('./toOrdinal'),
5 | toWords: require('./toWords'),
6 | toWordsOrdinal: require('./toWordsOrdinal')
7 | };
8 |
--------------------------------------------------------------------------------
/ROADMAP.md:
--------------------------------------------------------------------------------
1 | # Number To Words — Roadmap
2 |
3 | ### Version 2.0
4 | - Rework the API
5 | - Add pluggable languages files for multi-language support
6 | - Remove 1.x deprecated code
7 | - Run tests with Karma
8 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "node": true
5 | },
6 | "parserOptions": {
7 | "ecmaVersion": 5,
8 | "sourceType": "script"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/isSafeNumber.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var MAX_SAFE_INTEGER = require('./maxSafeInteger');
4 |
5 | function isSafeNumber(value) {
6 | return typeof value === 'number' && Math.abs(value) <= MAX_SAFE_INTEGER;
7 | }
8 |
9 | module.exports = isSafeNumber;
10 |
--------------------------------------------------------------------------------
/src/isFinite.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // Simplified https://gist.github.com/marlun78/885eb0021e980c6ce0fb
4 | function isFinite(value) {
5 | return !(typeof value !== 'number' || value !== value || value === Infinity || value === -Infinity);
6 | }
7 |
8 | module.exports = isFinite;
9 |
--------------------------------------------------------------------------------
/src/toWordsOrdinal.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var makeOrdinal = require('./makeOrdinal');
4 | var toWords = require('./toWords');
5 |
6 | /**
7 | * Converts a number into ordinal words.
8 | * @example toWordsOrdinal(12) => 'twelfth'
9 | * @param {number|string} number
10 | * @returns {string}
11 | */
12 | function toWordsOrdinal(number) {
13 | var words = toWords(number);
14 | return makeOrdinal(words);
15 | }
16 |
17 | module.exports = toWordsOrdinal;
18 |
--------------------------------------------------------------------------------
/spec/indexSpec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var index = typeof require !== 'undefined' ? require('../src') : window.numberToWords;
4 |
5 | describe('index', function () {
6 | it('should expose a toOrdinal method', function () {
7 | expect(index.toOrdinal).toEqual(jasmine.any(Function));
8 | });
9 | it('should expose a toWords method', function () {
10 | expect(index.toWords).toEqual(jasmine.any(Function));
11 | });
12 | it('should expose a toWordsOrdinal method', function () {
13 | expect(index.toWordsOrdinal).toEqual(jasmine.any(Function));
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Unix-style newlines with a newline ending every file
7 | [*]
8 | end_of_line = lf
9 | insert_final_newline = true
10 |
11 | # Matches multiple files with brace expansion notation
12 | # Set default charset
13 | [*.{css,js,json}]
14 | charset = utf-8
15 | indent_style = space
16 | indent_size = 4
17 |
18 | # Tab indentation (no size specified)
19 | [Makefile]
20 | indent_style = tab
21 |
22 | # Matches the exact files either package.json
23 | [{package.json}]
24 | indent_style = space
25 | indent_size = 2
26 |
--------------------------------------------------------------------------------
/spec/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Jasmine Spec Runner
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/wrapBundle.tmpl:
--------------------------------------------------------------------------------
1 | /*!
2 | * Number-To-Words util
3 | * @version v<%= data.version %>
4 | * @link <%= data.homepage %>
5 | * @author <%= data.author %>
6 | * @contributors <%= data.contributors %>
7 | * @license <%= data.license %>
8 | */
9 | (function () {
10 | 'use strict';
11 |
12 | var root = typeof self == 'object' && self.self === self && self ||
13 | typeof global == 'object' && global.global === global && global ||
14 | this;
15 |
16 | <%= data.contents %>
17 |
18 | var numberToWords = {
19 | toOrdinal: toOrdinal,
20 | toWords: toWords,
21 | toWordsOrdinal: toWordsOrdinal
22 | };
23 |
24 | if (typeof exports != 'undefined') {
25 | if (typeof module != 'undefined' && module.exports) {
26 | exports = module.exports = numberToWords;
27 | }
28 | exports.numberToWords = numberToWords;
29 | } else {
30 | root.numberToWords = numberToWords;
31 | }
32 |
33 | }());
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Martin Eneqvist (https://github.com/marlun78)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/src/toOrdinal.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var isFinite = require('./isFinite');
4 | var isSafeNumber = require('./isSafeNumber');
5 |
6 | /**
7 | * Converts an integer into a string with an ordinal postfix.
8 | * If number is decimal, the decimals will be removed.
9 | * @example toOrdinal(12) => '12th'
10 | * @param {number|string} number
11 | * @returns {string}
12 | */
13 | function toOrdinal(number) {
14 | var num = parseInt(number, 10);
15 |
16 | if (!isFinite(num)) {
17 | throw new TypeError(
18 | 'Not a finite number: ' + number + ' (' + typeof number + ')'
19 | );
20 | }
21 | if (!isSafeNumber(num)) {
22 | throw new RangeError(
23 | 'Input is not a safe number, it’s either too large or too small.'
24 | );
25 | }
26 | var str = String(num);
27 | var lastTwoDigits = Math.abs(num % 100);
28 | var betweenElevenAndThirteen = lastTwoDigits >= 11 && lastTwoDigits <= 13;
29 | var lastChar = str.charAt(str.length - 1);
30 | return str + (betweenElevenAndThirteen ? 'th'
31 | : lastChar === '1' ? 'st'
32 | : lastChar === '2' ? 'nd'
33 | : lastChar === '3' ? 'rd'
34 | : 'th');
35 | }
36 |
37 | module.exports = toOrdinal;
38 |
--------------------------------------------------------------------------------
/spec/isSafeNumberSpec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var MAX_SAFE_INTEGER = require('../src/maxSafeInteger');
4 | var isSafeNumber = require('../src/isSafeNumber');
5 |
6 | describe('isSafeNumber', function() {
7 | it('should return true if input is a number between -MAX_SAFE_INTEGER and MAX_SAFE_INTEGER (including)', function() {
8 | expect(isSafeNumber(-MAX_SAFE_INTEGER)).toBe(true);
9 | expect(isSafeNumber(-1)).toBe(true);
10 | expect(isSafeNumber(0)).toBe(true);
11 | expect(isSafeNumber(1)).toBe(true);
12 | expect(isSafeNumber(MAX_SAFE_INTEGER)).toBe(true);
13 | });
14 | it('should return false if input is too large or too small', function() {
15 | var unsafe = MAX_SAFE_INTEGER + 100;
16 |
17 | expect(isSafeNumber(unsafe)).toBe(false);
18 | expect(isSafeNumber(-unsafe)).toBe(false);
19 | });
20 | it('should return false if input is not a number', function() {
21 | expect(isSafeNumber()).toBe(false);
22 | expect(isSafeNumber(null)).toBe(false);
23 | expect(isSafeNumber([])).toBe(false);
24 | expect(isSafeNumber({})).toBe(false);
25 | expect(isSafeNumber('')).toBe(false);
26 | expect(isSafeNumber('x')).toBe(false);
27 | expect(isSafeNumber(function() {})).toBe(false);
28 | expect(isSafeNumber(NaN)).toBe(false);
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "number-to-words",
3 | "description": "Contains some util methods for converting numbers into words, ordinal words and ordinal numbers.",
4 | "version": "1.2.4",
5 | "main": "./numberToWords.min.js",
6 | "authors": [
7 | "Martin Eneqvist (https://github.com/marlun78)"
8 | ],
9 | "contributors": [
10 | "Aleksey Pilyugin (https://github.com/pilyugin)",
11 | "Jeremiah Hall (https://github.com/jeremiahrhall)",
12 | "Adriano Melo (https://github.com/adrianomelo)",
13 | "dmrzn (https://github.com/dmrzn)"
14 | ],
15 | "homepage": "https://github.com/marlun78/number-to-words",
16 | "moduleType": [
17 | "globals",
18 | "node"
19 | ],
20 | "repository": {
21 | "type": "git",
22 | "url": "https://github.com/marlun78/number-to-words"
23 | },
24 | "keywords": [
25 | "converter",
26 | "number",
27 | "ordinal",
28 | "string",
29 | "tool",
30 | "word"
31 | ],
32 | "license": "MIT",
33 | "ignore": [
34 | "bower_components",
35 | "node_modules",
36 | "spec",
37 | ".editorconfig",
38 | ".eslint",
39 | ".npmrc",
40 | ".prettierrc",
41 | "gulpfile.js",
42 | "wrapBundle.tmpl",
43 | "wrapEach.tmpl"
44 | ]
45 | }
46 |
--------------------------------------------------------------------------------
/src/makeOrdinal.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var ENDS_WITH_DOUBLE_ZERO_PATTERN = /(hundred|thousand|(m|b|tr|quadr)illion)$/;
4 | var ENDS_WITH_TEEN_PATTERN = /teen$/;
5 | var ENDS_WITH_Y_PATTERN = /y$/;
6 | var ENDS_WITH_ZERO_THROUGH_TWELVE_PATTERN = /(zero|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve)$/;
7 | var ordinalLessThanThirteen = {
8 | zero: 'zeroth',
9 | one: 'first',
10 | two: 'second',
11 | three: 'third',
12 | four: 'fourth',
13 | five: 'fifth',
14 | six: 'sixth',
15 | seven: 'seventh',
16 | eight: 'eighth',
17 | nine: 'ninth',
18 | ten: 'tenth',
19 | eleven: 'eleventh',
20 | twelve: 'twelfth'
21 | };
22 |
23 | /**
24 | * Converts a number-word into an ordinal number-word.
25 | * @example makeOrdinal('one') => 'first'
26 | * @param {string} words
27 | * @returns {string}
28 | */
29 | function makeOrdinal(words) {
30 | // Ends with *00 (100, 1000, etc.) or *teen (13, 14, 15, 16, 17, 18, 19)
31 | if (ENDS_WITH_DOUBLE_ZERO_PATTERN.test(words) || ENDS_WITH_TEEN_PATTERN.test(words)) {
32 | return words + 'th';
33 | }
34 | // Ends with *y (20, 30, 40, 50, 60, 70, 80, 90)
35 | else if (ENDS_WITH_Y_PATTERN.test(words)) {
36 | return words.replace(ENDS_WITH_Y_PATTERN, 'ieth');
37 | }
38 | // Ends with one through twelve
39 | else if (ENDS_WITH_ZERO_THROUGH_TWELVE_PATTERN.test(words)) {
40 | return words.replace(ENDS_WITH_ZERO_THROUGH_TWELVE_PATTERN, replaceWithOrdinalVariant);
41 | }
42 | return words;
43 | }
44 |
45 | function replaceWithOrdinalVariant(match, numberWord) {
46 | return ordinalLessThanThirteen[numberWord];
47 | }
48 |
49 | module.exports = makeOrdinal;
50 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var fs = require('fs');
4 | var gulp = require('gulp');
5 | var gulpPlugins = {
6 | concat: require('gulp-concat'),
7 | rename: require('gulp-rename'),
8 | replace: require('gulp-replace'),
9 | uglify: require('gulp-uglify'),
10 | wrap: require('gulp-wrap')
11 | };
12 | var log = require('fancy-log');
13 | var license = require('uglify-save-license');
14 |
15 | var pkg = require('./package.json');
16 |
17 | function bundleTask() {
18 | var USE_STRICT_PATTERN = /(['"]use strict['"];?\n?)/g;
19 | var REQUIRE_PATTERN = /((?:var |,)[^=]+=\s*require\([^\)]+\);?\n?)/g;
20 | var EXPORT_PATTERN = /((?:module\.)?exports\s*=\s*[^,;]+;?\n?)/g;
21 |
22 | var files = [
23 | './src/maxSafeInteger.js',
24 | './src/isFinite.js',
25 | './src/isSafeNumber.js',
26 | './src/makeOrdinal.js',
27 | './src/toOrdinal.js',
28 | './src/toWords.js',
29 | './src/toWordsOrdinal.js'
30 | ];
31 |
32 | return gulp.src(files)
33 | .on('error', log.error)
34 | .pipe(gulpPlugins.wrap({ src: 'wrapEach.tmpl' }))
35 | .pipe(gulpPlugins.replace(USE_STRICT_PATTERN, ''))
36 | .pipe(gulpPlugins.replace(REQUIRE_PATTERN, ''))
37 | .pipe(gulpPlugins.replace(EXPORT_PATTERN, ''))
38 | .pipe(gulpPlugins.concat('numberToWords.js'))
39 | .pipe(gulpPlugins.wrap({ src: 'wrapBundle.tmpl' }, pkg, { variable: 'data' }))
40 | .pipe(gulp.dest('./'))
41 | // Minified version
42 | .pipe(gulpPlugins.uglify({ output: { comments: license } }))
43 | .pipe(gulpPlugins.rename('numberToWords.min.js'))
44 | .pipe(gulp.dest('./'));
45 | }
46 |
47 | module.exports = {
48 | build: gulp.parallel(bundleTask)
49 | };
50 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "number-to-words",
3 | "description": "Contains some util methods for converting numbers into words, ordinal words and ordinal numbers.",
4 | "version": "1.2.4",
5 | "main": "./src",
6 | "browser": "./numberToWords.min.js",
7 | "author": "Martin Eneqvist (https://github.com/marlun78)",
8 | "contributors": [
9 | "Aleksey Pilyugin (https://github.com/pilyugin)",
10 | "Jeremiah Hall (https://github.com/jeremiahrhall)",
11 | "Adriano Melo (https://github.com/adrianomelo)",
12 | "dmrzn (https://github.com/dmrzn)"
13 | ],
14 | "devDependencies": {
15 | "eslint": "5.3.0",
16 | "fancy-log": "1.3.2",
17 | "gulp": "4.0.0",
18 | "gulp-concat": "2.6.1",
19 | "gulp-rename": "1.4.0",
20 | "gulp-replace": "1.0.0",
21 | "gulp-uglify": "3.0.1",
22 | "gulp-wrap": "0.14.0",
23 | "http-server": "0.11.1",
24 | "jasmine": "3.2.0",
25 | "phantomjs-prebuilt": "2.1.16",
26 | "uglify-save-license": "0.4.1"
27 | },
28 | "scripts": {
29 | "build": "gulp build",
30 | "lint": "node node_modules/eslint/bin/eslint.js .",
31 | "test": "npm run lint && npm run test:node",
32 | "test:node": "jasmine",
33 | "test:phantom": "phantomjs ./spec/phantom/run-jasmine3.js 'http://localhost:3456/spec/'",
34 | "test:server": "http-server ./ -p 3456 -c-1"
35 | },
36 | "repository": {
37 | "type": "git",
38 | "url": "https://github.com/marlun78/number-to-words"
39 | },
40 | "license": "MIT",
41 | "bugs": {
42 | "url": "https://github.com/marlun78/number-to-words/issues"
43 | },
44 | "homepage": "https://github.com/marlun78/number-to-words",
45 | "keywords": [
46 | "converter",
47 | "number",
48 | "ordinal",
49 | "string",
50 | "tool",
51 | "word"
52 | ]
53 | }
54 |
--------------------------------------------------------------------------------
/spec/toOrdinalSpec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var toOrdinal = typeof require !== 'undefined' ? require('../src/toOrdinal') : window.numberToWords.toOrdinal;
4 | var MAX_SAFE_INTEGER = 9007199254740991;
5 |
6 | describe('toOrdinal', function () {
7 | var tests = [
8 | { input: -121, expect: '-121st' },
9 | { input: -13, expect: '-13th' },
10 | { input: -12, expect: '-12th' },
11 | { input: -11, expect: '-11th' },
12 | { input: -3, expect: '-3rd' },
13 | { input: -2, expect: '-2nd' },
14 | { input: -1, expect: '-1st' },
15 | { input: 0, expect: '0th' },
16 | { input: 1, expect: '1st' },
17 | { input: 1.9, expect: '1st' },
18 | { input: 2, expect: '2nd' },
19 | { input: 3, expect: '3rd' },
20 | { input: 4, expect: '4th' },
21 | { input: 5, expect: '5th' },
22 | { input: 6, expect: '6th' },
23 | { input: 7, expect: '7th' },
24 | { input: 8, expect: '8th' },
25 | { input: 9, expect: '9th' },
26 | { input: 10, expect: '10th' },
27 | { input: 11, expect: '11th' },
28 | { input: 12, expect: '12th' },
29 | { input: 13, expect: '13th' },
30 | { input: 121, expect: '121st' }
31 | ];
32 |
33 | function addTest(test) {
34 | it('should, if passed ' + test.input + ', return ' + test.expect, function () {
35 | expect(toOrdinal(test.input)).toEqual(test.expect);
36 | });
37 | }
38 |
39 | tests.forEach(addTest);
40 |
41 | it('should throw a RangeError if input is greater or lesser than MAX_SAFE_INTEGER', function() {
42 | var unsafe = MAX_SAFE_INTEGER + 100;
43 |
44 | expect(function() {
45 | toOrdinal(unsafe);
46 | }).toThrowError(/Input is not a safe number/);
47 |
48 | expect(function() {
49 | toOrdinal(-unsafe);
50 | }).toThrowError(/Input is not a safe number/);
51 | });
52 | });
53 |
--------------------------------------------------------------------------------
/numberToWords.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Number-To-Words util
3 | * @version v1.2.4
4 | * @link https://github.com/marlun78/number-to-words
5 | * @author Martin Eneqvist (https://github.com/marlun78)
6 | * @contributors Aleksey Pilyugin (https://github.com/pilyugin),Jeremiah Hall (https://github.com/jeremiahrhall),Adriano Melo (https://github.com/adrianomelo),dmrzn (https://github.com/dmrzn)
7 | * @license MIT
8 | */
9 | !function(){"use strict";var e="object"==typeof self&&self.self===self&&self||"object"==typeof global&&global.global===global&&global||this,t=9007199254740991;function f(e){return!("number"!=typeof e||e!=e||e===1/0||e===-1/0)}function l(e){return"number"==typeof e&&Math.abs(e)<=t}var n=/(hundred|thousand|(m|b|tr|quadr)illion)$/,r=/teen$/,o=/y$/,i=/(zero|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve)$/,s={zero:"zeroth",one:"first",two:"second",three:"third",four:"fourth",five:"fifth",six:"sixth",seven:"seventh",eight:"eighth",nine:"ninth",ten:"tenth",eleven:"eleventh",twelve:"twelfth"};function h(e){return n.test(e)||r.test(e)?e+"th":o.test(e)?e.replace(o,"ieth"):i.test(e)?e.replace(i,a):e}function a(e,t){return s[t]}var u=10,d=100,p=1e3,v=1e6,b=1e9,y=1e12,c=1e15,g=9007199254740992,m=["zero","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"],w=["zero","ten","twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"];function x(e,t){var n,r=parseInt(e,10);if(!f(r))throw new TypeError("Not a finite number: "+e+" ("+typeof e+")");if(!l(r))throw new RangeError("Input is not a safe number, it’s either too large or too small.");return n=function e(t){var n,r,o=arguments[1];if(0===t)return o?o.join(" ").replace(/,$/,""):"zero";o||(o=[]);t<0&&(o.push("minus"),t=Math.abs(t));t<20?(n=0,r=m[t]):t “21st”
23 | ```
24 |
25 | #### `toWords(number)`
26 | Converts an integer into words.
27 | If number is decimal, the decimals will be removed.
28 | ```js
29 | var converter = require('number-to-words');
30 | converter.toWords(13); // => “thirteen”
31 |
32 | // Decimal numbers:
33 | converter.toWords(2.9); // => “two”
34 |
35 | // Negative numbers:
36 | converter.toWords(-3); // => “minus three”
37 |
38 | // Large numbers:
39 | converter.toWords(9007199254740992); // => “nine quadrillion, seven trillion, one hundred ninety-nine billion, two hundred fifty-four million, seven hundred forty thousand, nine hundred ninety-two”
40 | ```
41 |
42 | #### `toWordsOrdinal(number)`
43 | Converts a number into ordinal words.
44 | If number is decimal, the decimals will be removed.
45 | ```js
46 | var converter = require('number-to-words');
47 | converter.toWordsOrdinal(21); // => “twenty-first”
48 | ```
49 |
50 |
51 | ### Contributions, Comments and Bugs
52 | Contributions, comments and/or bug reports are much appreciated. Open a pull request or add comments on the
53 | [issues page](https://github.com/marlun78/number-to-words/issues). Thanks!
54 |
55 |
56 | ### Upcoming v2.0
57 | See [roadmap](ROADMAP.md) for details.
58 |
59 |
60 | ### Change Log
61 |
62 | ##### Version 1.2.4 (final 1.x release)
63 | - Bug fix in `toOrdinal`. When passed -11, -12 and -13 it returned an incorrect suffix ([#15](https://github.com/marlun78/number-to-words/issues/15)). Thanks to @dmrzn.
64 | - `toOrdinal` and `toWords` now throws a more precise error when passed an unsafe number ([#13](https://github.com/marlun78/number-to-words/pull/13)). Thanks to @adrianomelo.
65 |
66 | ##### Version 1.2.3
67 | - Bug fix in `isFinite` for Phantom and IE ([#10](https://github.com/marlun78/number-to-words/pull/10)). Thanks to @jeremiahrhall.
68 |
69 | ##### Version 1.2.2
70 | - Bug fix in `toOrdinal`. Input 11, 12, and 13 now yields the correct suffix ([#8](https://github.com/marlun78/number-to-words/pull/8)). Thanks to @pilyugin.
71 |
72 | ##### Version 1.2.1
73 | - Bower package
74 |
75 | ##### Version 1.2.0
76 | - Bundles are now available for browsers (`./numberToWords.js` and `./numberToWords.min.js`). They export a global `numberToWords` variable.
77 | - Made unit tests runnable in browser. To run the unit tests in the browser, start a local server and visit localhost/spec with a browser.
78 | - `toOrdinal`, `toWords` and `toWordsOrdinal` now also allow string values as input (replaced `Math.floor` with `parseInt`).
79 |
80 | ##### 1.1.0
81 | - New methods `toOrdinal` and `toWordsOrdinal`
82 | - Deprecated `toWords` second optional `asOrdinal` parameter, use `toWordsOrdinal()`-method instead
83 | - `toWords` now converts any decimal input to an integer (with `Math.floor`)
84 | - Bug fixed returning _“zeroth”_ instead of _“zero”_ when converting a number word into its ordinal
85 |
86 | ##### 1.0.1
87 | - Minor package tweaks
88 |
89 | ##### 1.0.0
90 | - Initial release
91 |
--------------------------------------------------------------------------------
/src/toWords.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var makeOrdinal = require('./makeOrdinal');
4 | var isFinite = require('./isFinite');
5 | var isSafeNumber = require('./isSafeNumber');
6 |
7 | var TEN = 10;
8 | var ONE_HUNDRED = 100;
9 | var ONE_THOUSAND = 1000;
10 | var ONE_MILLION = 1000000;
11 | var ONE_BILLION = 1000000000; // 1.000.000.000 (9)
12 | var ONE_TRILLION = 1000000000000; // 1.000.000.000.000 (12)
13 | var ONE_QUADRILLION = 1000000000000000; // 1.000.000.000.000.000 (15)
14 | var MAX = 9007199254740992; // 9.007.199.254.740.992 (15)
15 |
16 | var LESS_THAN_TWENTY = [
17 | 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten',
18 | 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'
19 | ];
20 |
21 | var TENTHS_LESS_THAN_HUNDRED = [
22 | 'zero', 'ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'
23 | ];
24 |
25 | /**
26 | * Converts an integer into words.
27 | * If number is decimal, the decimals will be removed.
28 | * @example toWords(12) => 'twelve'
29 | * @param {number|string} number
30 | * @param {boolean} [asOrdinal] - Deprecated, use toWordsOrdinal() instead!
31 | * @returns {string}
32 | */
33 | function toWords(number, asOrdinal) {
34 | var words;
35 | var num = parseInt(number, 10);
36 |
37 | if (!isFinite(num)) {
38 | throw new TypeError(
39 | 'Not a finite number: ' + number + ' (' + typeof number + ')'
40 | );
41 | }
42 | if (!isSafeNumber(num)) {
43 | throw new RangeError(
44 | 'Input is not a safe number, it’s either too large or too small.'
45 | );
46 | }
47 | words = generateWords(num);
48 | return asOrdinal ? makeOrdinal(words) : words;
49 | }
50 |
51 | function generateWords(number) {
52 | var remainder, word,
53 | words = arguments[1];
54 |
55 | // We’re done
56 | if (number === 0) {
57 | return !words ? 'zero' : words.join(' ').replace(/,$/, '');
58 | }
59 | // First run
60 | if (!words) {
61 | words = [];
62 | }
63 | // If negative, prepend “minus”
64 | if (number < 0) {
65 | words.push('minus');
66 | number = Math.abs(number);
67 | }
68 |
69 | if (number < 20) {
70 | remainder = 0;
71 | word = LESS_THAN_TWENTY[number];
72 |
73 | } else if (number < ONE_HUNDRED) {
74 | remainder = number % TEN;
75 | word = TENTHS_LESS_THAN_HUNDRED[Math.floor(number / TEN)];
76 | // In case of remainder, we need to handle it here to be able to add the “-”
77 | if (remainder) {
78 | word += '-' + LESS_THAN_TWENTY[remainder];
79 | remainder = 0;
80 | }
81 |
82 | } else if (number < ONE_THOUSAND) {
83 | remainder = number % ONE_HUNDRED;
84 | word = generateWords(Math.floor(number / ONE_HUNDRED)) + ' hundred';
85 |
86 | } else if (number < ONE_MILLION) {
87 | remainder = number % ONE_THOUSAND;
88 | word = generateWords(Math.floor(number / ONE_THOUSAND)) + ' thousand,';
89 |
90 | } else if (number < ONE_BILLION) {
91 | remainder = number % ONE_MILLION;
92 | word = generateWords(Math.floor(number / ONE_MILLION)) + ' million,';
93 |
94 | } else if (number < ONE_TRILLION) {
95 | remainder = number % ONE_BILLION;
96 | word = generateWords(Math.floor(number / ONE_BILLION)) + ' billion,';
97 |
98 | } else if (number < ONE_QUADRILLION) {
99 | remainder = number % ONE_TRILLION;
100 | word = generateWords(Math.floor(number / ONE_TRILLION)) + ' trillion,';
101 |
102 | } else if (number <= MAX) {
103 | remainder = number % ONE_QUADRILLION;
104 | word = generateWords(Math.floor(number / ONE_QUADRILLION)) +
105 | ' quadrillion,';
106 | }
107 |
108 | words.push(word);
109 | return generateWords(remainder, words);
110 | }
111 |
112 | module.exports = toWords;
113 |
--------------------------------------------------------------------------------
/spec/phantom/run-jasmine3.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var system = require('system');
3 |
4 | /**
5 | * Wait until the test condition is true or a timeout occurs. Useful for waiting
6 | * on a server response or for a ui change (fadeIn, etc.) to occur.
7 | *
8 | * @param testFx javascript condition that evaluates to a boolean,
9 | * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
10 | * as a callback function.
11 | * @param onReady what to do when testFx condition is fulfilled,
12 | * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
13 | * as a callback function.
14 | * @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
15 | */
16 | function waitFor(testFx, onReady, timeOutMillis) {
17 | var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timeout is 3s
18 | start = new Date().getTime(),
19 | condition = false,
20 | interval = setInterval(function() {
21 | if (new Date().getTime() - start < maxtimeOutMillis && !condition) {
22 | // If not time-out yet and condition not yet fulfilled
23 | condition =
24 | typeof testFx === 'string' ? eval(testFx) : testFx(); //< defensive code
25 | } else {
26 | if (!condition) {
27 | // If condition still not fulfilled (timeout but condition is 'false')
28 | console.log("'waitFor()' timeout");
29 | phantom.exit(1);
30 | } else {
31 | // Condition fulfilled (timeout and/or condition is 'true')
32 | console.log(
33 | "'waitFor()' finished in " +
34 | (new Date().getTime() - start) +
35 | 'ms.'
36 | );
37 | typeof onReady === 'string' ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
38 | clearInterval(interval); //< Stop this interval
39 | }
40 | }
41 | }, 100); //< repeat check every 100ms
42 | }
43 |
44 | if (system.args.length !== 2) {
45 | console.log('Usage: run-jasmine2.js URL');
46 | phantom.exit(1);
47 | }
48 |
49 | var page = require('webpage').create();
50 |
51 | // Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
52 | page.onConsoleMessage = function(msg) {
53 | console.log(msg);
54 | };
55 |
56 | page.open(system.args[1], function(status) {
57 | if (status !== 'success') {
58 | console.log('Unable to access network');
59 | phantom.exit();
60 | } else {
61 | waitFor(
62 | function() {
63 | return page.evaluate(function() {
64 | var summary = document.body.querySelector(
65 | '.jasmine-results .jasmine-summary'
66 | );
67 | var duration = document.body.querySelector(
68 | '.jasmine-duration'
69 | );
70 |
71 | return summary !== null && duration !== null;
72 | });
73 | },
74 | function() {
75 | var exitCode = page.evaluate(function() {
76 | console.log('');
77 |
78 | var title = 'Jasmine';
79 | var version = document.body.querySelector(
80 | '.jasmine-version'
81 | ).innerText;
82 | console.log(title + ' ' + version);
83 |
84 | var result = document.body.querySelector(
85 | '.jasmine-overall-result.jasmine-bar'
86 | ).innerText;
87 | console.log(result);
88 |
89 | var duration = document.body.querySelector(
90 | '.jasmine-duration'
91 | ).innerText;
92 | console.log(duration);
93 |
94 | var list = document.body.querySelectorAll(
95 | '.jasmine-results > .jasmine-failures > .jasmine-spec-detail.jasmine-failed'
96 | );
97 | if (list && list.length > 0) {
98 | console.log('');
99 | console.log(list.length + ' test(s) FAILED:');
100 | for (i = 0; i < list.length; ++i) {
101 | var el = list[i],
102 | desc = el.querySelector('.jasmine-description'),
103 | msg = el.querySelector(
104 | '.jasmine-messages > .jasmine-result-message'
105 | );
106 | console.log('');
107 | console.log(desc.innerText);
108 | console.log(' ' + msg.innerText);
109 | console.log('');
110 | }
111 | return 1;
112 | } else {
113 | return 0;
114 | }
115 | });
116 | phantom.exit(exitCode);
117 | }
118 | );
119 | }
120 | });
121 |
--------------------------------------------------------------------------------
/spec/toWordsSpec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var MAX_SAFE_INTEGER = 9007199254740991;
4 | var toWords = typeof require !== 'undefined' ? require('../src/toWords') : window.numberToWords.toWords;
5 |
6 | describe('toWords', function () {
7 | var tests = [
8 | { input: -1, expect: 'minus one' },
9 | { input: 0, expect: 'zero' },
10 | { input: 1, expect: 'one' },
11 | { input: 1.9, expect: 'one' },
12 | { input: 2, expect: 'two' },
13 | { input: 3, expect: 'three' },
14 | { input: 4, expect: 'four' },
15 | { input: 5, expect: 'five' },
16 | { input: 6, expect: 'six' },
17 | { input: 7, expect: 'seven' },
18 | { input: 8, expect: 'eight' },
19 | { input: 9, expect: 'nine' },
20 | { input: 10, expect: 'ten' },
21 | { input: 11, expect: 'eleven' },
22 | { input: 12, expect: 'twelve' },
23 | { input: 13, expect: 'thirteen' },
24 | { input: 14, expect: 'fourteen' },
25 | { input: 15, expect: 'fifteen' },
26 | { input: 16, expect: 'sixteen' },
27 | { input: 17, expect: 'seventeen' },
28 | { input: 18, expect: 'eighteen' },
29 | { input: 19, expect: 'nineteen' },
30 | { input: 20, expect: 'twenty' },
31 | { input: 22, expect: 'twenty-two' },
32 | { input: 33, expect: 'thirty-three' },
33 | { input: 44, expect: 'forty-four' },
34 | { input: 55, expect: 'fifty-five' },
35 | { input: 66, expect: 'sixty-six' },
36 | { input: 77, expect: 'seventy-seven' },
37 | { input: 88, expect: 'eighty-eight' },
38 | { input: 99, expect: 'ninety-nine' },
39 | { input: 100, expect: 'one hundred' },
40 | { input: 111, expect: 'one hundred eleven' },
41 | { input: 1000, expect: 'one thousand' },
42 | { input: 2222, expect: 'two thousand, two hundred twenty-two' },
43 | { input: 10000, expect: 'ten thousand' },
44 | { input: 33333, expect: 'thirty-three thousand, three hundred thirty-three' },
45 | { input: 100000, expect: 'one hundred thousand' },
46 | { input: 444444, expect: 'four hundred forty-four thousand, four hundred forty-four' },
47 | { input: 1000000, expect: 'one million' },
48 | { input: 5555555, expect: 'five million, five hundred fifty-five thousand, five hundred fifty-five' },
49 | { input: 10000000, expect: 'ten million' },
50 | { input: 66666666, expect: 'sixty-six million, six hundred sixty-six thousand, six hundred sixty-six' },
51 | { input: 100000000, expect: 'one hundred million' },
52 | {
53 | input: 777777777,
54 | expect: 'seven hundred seventy-seven million, seven hundred seventy-seven thousand, seven hundred seventy-seven'
55 | },
56 | { input: 1000000000, expect: 'one billion' },
57 | {
58 | input: 8888888888,
59 | expect: 'eight billion, eight hundred eighty-eight million, eight hundred eighty-eight thousand, eight hundred eighty-eight'
60 | },
61 | { input: 10000000000, expect: 'ten billion' },
62 | {
63 | input: 99999999999,
64 | expect: 'ninety-nine billion, nine hundred ninety-nine million, nine hundred ninety-nine thousand, nine hundred ninety-nine'
65 | },
66 | { input: 100000000000, expect: 'one hundred billion' },
67 | {
68 | input: 111111111111,
69 | expect: 'one hundred eleven billion, one hundred eleven million, one hundred eleven thousand, one hundred eleven'
70 | },
71 | { input: 1000000000000, expect: 'one trillion' },
72 | {
73 | input: 2222222222222,
74 | expect: 'two trillion, two hundred twenty-two billion, two hundred twenty-two million, two hundred twenty-two thousand, two hundred twenty-two'
75 | },
76 | { input: 10000000000000, expect: 'ten trillion' },
77 | {
78 | input: 33333333333333,
79 | expect: 'thirty-three trillion, three hundred thirty-three billion, three hundred thirty-three million, three hundred thirty-three thousand, three hundred thirty-three'
80 | },
81 | { input: 100000000000000, expect: 'one hundred trillion' },
82 | {
83 | input: 444444444444444,
84 | expect: 'four hundred forty-four trillion, four hundred forty-four billion, four hundred forty-four million, four hundred forty-four thousand, four hundred forty-four'
85 | },
86 | { input: 1000000000000000, expect: 'one quadrillion' },
87 | {
88 | input: 5555555555555555,
89 | expect: 'five quadrillion, five hundred fifty-five trillion, five hundred fifty-five billion, five hundred fifty-five million, five hundred fifty-five thousand, five hundred fifty-five'
90 | },
91 | {
92 | input: MAX_SAFE_INTEGER,
93 | expect: 'nine quadrillion, seven trillion, one hundred ninety-nine billion, two hundred fifty-four million, seven hundred forty thousand, nine hundred ninety-one'
94 | }
95 | ];
96 |
97 | function addTest(test) {
98 | it('should, if passed ' + formatNumber(test.input) + ', return ' + test.expect, function () {
99 | expect(toWords(test.input)).toEqual(test.expect);
100 | });
101 | }
102 |
103 | tests.forEach(addTest);
104 |
105 | // Note! This is deprecated, use toWordsOrdinal() instead!
106 | it('should return the number with an ordinal word if passed a second truthy argument', function () {
107 | expect(toWords(1, true)).toEqual('first');
108 | expect(toWords(2, true)).toEqual('second');
109 | expect(toWords(3, true)).toEqual('third');
110 | expect(toWords(10, true)).toEqual('tenth');
111 | expect(toWords(17, true)).toEqual('seventeenth');
112 | expect(toWords(30, true)).toEqual('thirtieth');
113 | expect(toWords(123, true)).toEqual('one hundred twenty-third');
114 | });
115 |
116 | it('should throw a RangeError if input is greater or lesser than MAX_SAFE_INTEGER', function() {
117 | var unsafe = MAX_SAFE_INTEGER + 100;
118 |
119 | expect(function() {
120 | toWords(unsafe);
121 | }).toThrowError(/Input is not a safe number/);
122 |
123 | expect(function() {
124 | toWords(-unsafe);
125 | }).toThrowError(/Input is not a safe number/);
126 | });
127 | });
128 |
129 | function formatNumber(number) {
130 | var result = String(number).split('').reverse().map(function (num, index) {
131 | if (index % 3 === 2) return '.' + num;
132 | return num;
133 | }).reverse();
134 | var length = result.length;
135 | return result.join('') + ' (' + length + ')';
136 | }
137 |
--------------------------------------------------------------------------------
/numberToWords.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Number-To-Words util
3 | * @version v1.2.4
4 | * @link https://github.com/marlun78/number-to-words
5 | * @author Martin Eneqvist (https://github.com/marlun78)
6 | * @contributors Aleksey Pilyugin (https://github.com/pilyugin),Jeremiah Hall (https://github.com/jeremiahrhall),Adriano Melo (https://github.com/adrianomelo),dmrzn (https://github.com/dmrzn)
7 | * @license MIT
8 | */
9 | (function () {
10 | 'use strict';
11 |
12 | var root = typeof self == 'object' && self.self === self && self ||
13 | typeof global == 'object' && global.global === global && global ||
14 | this;
15 |
16 | // ========== file: /src/maxSafeInteger.js ==========
17 |
18 | var MAX_SAFE_INTEGER = 9007199254740991;
19 |
20 |
21 | // ========== file: /src/isFinite.js ==========
22 |
23 | // Simplified https://gist.github.com/marlun78/885eb0021e980c6ce0fb
24 | function isFinite(value) {
25 | return !(typeof value !== 'number' || value !== value || value === Infinity || value === -Infinity);
26 | }
27 |
28 |
29 | // ========== file: /src/isSafeNumber.js ==========
30 |
31 |
32 | function isSafeNumber(value) {
33 | return typeof value === 'number' && Math.abs(value) <= MAX_SAFE_INTEGER;
34 | }
35 |
36 |
37 | // ========== file: /src/makeOrdinal.js ==========
38 |
39 | var ENDS_WITH_DOUBLE_ZERO_PATTERN = /(hundred|thousand|(m|b|tr|quadr)illion)$/;
40 | var ENDS_WITH_TEEN_PATTERN = /teen$/;
41 | var ENDS_WITH_Y_PATTERN = /y$/;
42 | var ENDS_WITH_ZERO_THROUGH_TWELVE_PATTERN = /(zero|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve)$/;
43 | var ordinalLessThanThirteen = {
44 | zero: 'zeroth',
45 | one: 'first',
46 | two: 'second',
47 | three: 'third',
48 | four: 'fourth',
49 | five: 'fifth',
50 | six: 'sixth',
51 | seven: 'seventh',
52 | eight: 'eighth',
53 | nine: 'ninth',
54 | ten: 'tenth',
55 | eleven: 'eleventh',
56 | twelve: 'twelfth'
57 | };
58 |
59 | /**
60 | * Converts a number-word into an ordinal number-word.
61 | * @example makeOrdinal('one') => 'first'
62 | * @param {string} words
63 | * @returns {string}
64 | */
65 | function makeOrdinal(words) {
66 | // Ends with *00 (100, 1000, etc.) or *teen (13, 14, 15, 16, 17, 18, 19)
67 | if (ENDS_WITH_DOUBLE_ZERO_PATTERN.test(words) || ENDS_WITH_TEEN_PATTERN.test(words)) {
68 | return words + 'th';
69 | }
70 | // Ends with *y (20, 30, 40, 50, 60, 70, 80, 90)
71 | else if (ENDS_WITH_Y_PATTERN.test(words)) {
72 | return words.replace(ENDS_WITH_Y_PATTERN, 'ieth');
73 | }
74 | // Ends with one through twelve
75 | else if (ENDS_WITH_ZERO_THROUGH_TWELVE_PATTERN.test(words)) {
76 | return words.replace(ENDS_WITH_ZERO_THROUGH_TWELVE_PATTERN, replaceWithOrdinalVariant);
77 | }
78 | return words;
79 | }
80 |
81 | function replaceWithOrdinalVariant(match, numberWord) {
82 | return ordinalLessThanThirteen[numberWord];
83 | }
84 |
85 |
86 | // ========== file: /src/toOrdinal.js ==========
87 |
88 |
89 | /**
90 | * Converts an integer into a string with an ordinal postfix.
91 | * If number is decimal, the decimals will be removed.
92 | * @example toOrdinal(12) => '12th'
93 | * @param {number|string} number
94 | * @returns {string}
95 | */
96 | function toOrdinal(number) {
97 | var num = parseInt(number, 10);
98 |
99 | if (!isFinite(num)) {
100 | throw new TypeError(
101 | 'Not a finite number: ' + number + ' (' + typeof number + ')'
102 | );
103 | }
104 | if (!isSafeNumber(num)) {
105 | throw new RangeError(
106 | 'Input is not a safe number, it’s either too large or too small.'
107 | );
108 | }
109 | var str = String(num);
110 | var lastTwoDigits = Math.abs(num % 100);
111 | var betweenElevenAndThirteen = lastTwoDigits >= 11 && lastTwoDigits <= 13;
112 | var lastChar = str.charAt(str.length - 1);
113 | return str + (betweenElevenAndThirteen ? 'th'
114 | : lastChar === '1' ? 'st'
115 | : lastChar === '2' ? 'nd'
116 | : lastChar === '3' ? 'rd'
117 | : 'th');
118 | }
119 |
120 |
121 | // ========== file: /src/toWords.js ==========
122 |
123 |
124 | var TEN = 10;
125 | var ONE_HUNDRED = 100;
126 | var ONE_THOUSAND = 1000;
127 | var ONE_MILLION = 1000000;
128 | var ONE_BILLION = 1000000000; // 1.000.000.000 (9)
129 | var ONE_TRILLION = 1000000000000; // 1.000.000.000.000 (12)
130 | var ONE_QUADRILLION = 1000000000000000; // 1.000.000.000.000.000 (15)
131 | var MAX = 9007199254740992; // 9.007.199.254.740.992 (15)
132 |
133 | var LESS_THAN_TWENTY = [
134 | 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten',
135 | 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'
136 | ];
137 |
138 | var TENTHS_LESS_THAN_HUNDRED = [
139 | 'zero', 'ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'
140 | ];
141 |
142 | /**
143 | * Converts an integer into words.
144 | * If number is decimal, the decimals will be removed.
145 | * @example toWords(12) => 'twelve'
146 | * @param {number|string} number
147 | * @param {boolean} [asOrdinal] - Deprecated, use toWordsOrdinal() instead!
148 | * @returns {string}
149 | */
150 | function toWords(number, asOrdinal) {
151 | var words;
152 | var num = parseInt(number, 10);
153 |
154 | if (!isFinite(num)) {
155 | throw new TypeError(
156 | 'Not a finite number: ' + number + ' (' + typeof number + ')'
157 | );
158 | }
159 | if (!isSafeNumber(num)) {
160 | throw new RangeError(
161 | 'Input is not a safe number, it’s either too large or too small.'
162 | );
163 | }
164 | words = generateWords(num);
165 | return asOrdinal ? makeOrdinal(words) : words;
166 | }
167 |
168 | function generateWords(number) {
169 | var remainder, word,
170 | words = arguments[1];
171 |
172 | // We’re done
173 | if (number === 0) {
174 | return !words ? 'zero' : words.join(' ').replace(/,$/, '');
175 | }
176 | // First run
177 | if (!words) {
178 | words = [];
179 | }
180 | // If negative, prepend “minus”
181 | if (number < 0) {
182 | words.push('minus');
183 | number = Math.abs(number);
184 | }
185 |
186 | if (number < 20) {
187 | remainder = 0;
188 | word = LESS_THAN_TWENTY[number];
189 |
190 | } else if (number < ONE_HUNDRED) {
191 | remainder = number % TEN;
192 | word = TENTHS_LESS_THAN_HUNDRED[Math.floor(number / TEN)];
193 | // In case of remainder, we need to handle it here to be able to add the “-”
194 | if (remainder) {
195 | word += '-' + LESS_THAN_TWENTY[remainder];
196 | remainder = 0;
197 | }
198 |
199 | } else if (number < ONE_THOUSAND) {
200 | remainder = number % ONE_HUNDRED;
201 | word = generateWords(Math.floor(number / ONE_HUNDRED)) + ' hundred';
202 |
203 | } else if (number < ONE_MILLION) {
204 | remainder = number % ONE_THOUSAND;
205 | word = generateWords(Math.floor(number / ONE_THOUSAND)) + ' thousand,';
206 |
207 | } else if (number < ONE_BILLION) {
208 | remainder = number % ONE_MILLION;
209 | word = generateWords(Math.floor(number / ONE_MILLION)) + ' million,';
210 |
211 | } else if (number < ONE_TRILLION) {
212 | remainder = number % ONE_BILLION;
213 | word = generateWords(Math.floor(number / ONE_BILLION)) + ' billion,';
214 |
215 | } else if (number < ONE_QUADRILLION) {
216 | remainder = number % ONE_TRILLION;
217 | word = generateWords(Math.floor(number / ONE_TRILLION)) + ' trillion,';
218 |
219 | } else if (number <= MAX) {
220 | remainder = number % ONE_QUADRILLION;
221 | word = generateWords(Math.floor(number / ONE_QUADRILLION)) +
222 | ' quadrillion,';
223 | }
224 |
225 | words.push(word);
226 | return generateWords(remainder, words);
227 | }
228 |
229 |
230 | // ========== file: /src/toWordsOrdinal.js ==========
231 |
232 |
233 | /**
234 | * Converts a number into ordinal words.
235 | * @example toWordsOrdinal(12) => 'twelfth'
236 | * @param {number|string} number
237 | * @returns {string}
238 | */
239 | function toWordsOrdinal(number) {
240 | var words = toWords(number);
241 | return makeOrdinal(words);
242 | }
243 |
244 |
245 |
246 | var numberToWords = {
247 | toOrdinal: toOrdinal,
248 | toWords: toWords,
249 | toWordsOrdinal: toWordsOrdinal
250 | };
251 |
252 | if (typeof exports != 'undefined') {
253 | if (typeof module != 'undefined' && module.exports) {
254 | exports = module.exports = numberToWords;
255 | }
256 | exports.numberToWords = numberToWords;
257 | } else {
258 | root.numberToWords = numberToWords;
259 | }
260 |
261 | }());
--------------------------------------------------------------------------------