From c6b70ea725db52ea2ee1606716f2cb7b9e940805 Mon Sep 17 00:00:00 2001 From: Jan Linhart Date: Thu, 22 Oct 2015 09:30:56 +0200 Subject: [PATCH 1/3] Readme format fix --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f1abf0d..b87d3f6 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,7 @@ string concatenation) — and bind from left to right (yes, even exponentiation it’s simpler that way). Inside the first argument of the if function can be used these operators to compare expressions: + == Equal != Not equal > Greater than From ecc57e5819e2331a526b35a7d7863048f0cddf4d Mon Sep 17 00:00:00 2001 From: Jan Linhart Date: Thu, 22 Oct 2015 09:42:45 +0200 Subject: [PATCH 2/3] len(n) function added --- README.md | 1 + parser.js | 9 ++++++++- test/parserSpec.js | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b87d3f6..9e86abe 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,7 @@ These are not evaluated by simplify. atan2(y, x) Arc tangent of x/y. i.e. the angle between (0, 0) and (x, y) in radians. hypot(a,b) The square root of the sum of squares of its arguments. if(c, a, b) The condition function where c is condition, a is result if c is true, b is result if c is false + len(n) The character length of n. i.e. len(123) = 3 ### Tests ### diff --git a/parser.js b/parser.js index 83d0f40..a2d5b81 100644 --- a/parser.js +++ b/parser.js @@ -406,6 +406,11 @@ var Parser = (function (scope) { return cond ? yep : nope; } + function len(val) { + if (typeof val === 'undefined') val = ''; + return val.toString().length; + } + function append(a, b) { if (Object.prototype.toString.call(a) != "[object Array]") { return [a, b]; @@ -481,7 +486,8 @@ var Parser = (function (scope) { "pyt": hypot, // backward compat "pow": Math.pow, "atan2": Math.atan2, - "if": condition + "if": condition, + "len": len }; this.consts = { @@ -532,6 +538,7 @@ var Parser = (function (scope) { pow: Math.pow, atan2: Math.atan2, if: condition, + len: len, E: Math.E, PI: Math.PI }; diff --git a/test/parserSpec.js b/test/parserSpec.js index 6812be2..29431f4 100644 --- a/test/parserSpec.js +++ b/test/parserSpec.js @@ -177,6 +177,24 @@ describe("Parser", function() { expect(Parser.evaluate("if(3 and 6, if(45 > 5 * 11, 3 * 3, 2.4), 0)")).to.equal(2.4); }); }); + + describe("#len()", function() { + it("len(1)", function() { + expect(Parser.evaluate("len(1)")).to.equal(1); + }); + it("len(0)", function() { + expect(Parser.evaluate("len(0)")).to.equal(1); + }); + it("len()", function() { + expect(Parser.evaluate("len()")).to.equal(0); + }); + it("len(12345)", function() { + expect(Parser.evaluate("len(12345)")).to.equal(5); + }); + it("len('string')", function() { + expect(Parser.evaluate("len('string')")).to.equal(6); + }); + }); }); /* @todo From 3226224ec436c094841126607ab571f450b79f75 Mon Sep 17 00:00:00 2001 From: Jan Linhart Date: Thu, 22 Oct 2015 10:33:26 +0200 Subject: [PATCH 3/3] round has second parameter as number of decimal places --- README.md | 42 +++++++++++++++++++++--------------------- parser.js | 40 ++++++++++++++++++++++++++++++++++++++-- test/parserSpec.js | 21 +++++++++++++++++++++ 3 files changed, 80 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 9e86abe..e0b7ea6 100644 --- a/README.md +++ b/README.md @@ -148,27 +148,27 @@ only difference from an outside point of view, is that they cannot be called with multiple arguments and they are evaluated by the simplify method if their arguments are constant. - Function Description - sin(x) Sine of x (x is in radians) - cos(x) Cosine of x (x is in radians) - tan(x) Tangent of x (x is… well, you know) - asin(x) Arc sine of x (in radians) - acos(x) Arc cosine of x (in radians) - atan(x) Arc tangent of x (in radians) - sinh(x) Hyperbolic sine of x (x is in radians) - cosh(x) Hyperbolic cosine of x (x is in radians) - tanh(x) Hyperbolic tangent of x (x is… well, you know) - asinh(x) Hyperbolic arc sine of x (in radians) - acosh(x) Hyperbolic arc cosine of x (in radians) - atanh(x) Hyperbolic arc tangent of x (in radians) - sqrt(x) Square root of x. Result is NaN (Not a Number) if x is negative. - log(x) Natural logarithm of x (not base-10). It’s log instead of ln because that’s what JavaScript calls it. - abs(x) Absolute value (magnatude) of x - ceil(x) Ceiling of x — the smallest integer that’s >= x. - floor(x) Floor of x — the largest integer that’s <= x. - round(x) X, rounded to the nearest integer, using “gradeschool rounding”. - trunc(x) Integral part of a X, looks like floor(x) unless for negative number. - exp(x) ex (exponential/antilogarithm function with base e) Pre-defined functions + Function Description + sin(x) Sine of x (x is in radians) + cos(x) Cosine of x (x is in radians) + tan(x) Tangent of x (x is… well, you know) + asin(x) Arc sine of x (in radians) + acos(x) Arc cosine of x (in radians) + atan(x) Arc tangent of x (in radians) + sinh(x) Hyperbolic sine of x (x is in radians) + cosh(x) Hyperbolic cosine of x (x is in radians) + tanh(x) Hyperbolic tangent of x (x is… well, you know) + asinh(x) Hyperbolic arc sine of x (in radians) + acosh(x) Hyperbolic arc cosine of x (in radians) + atanh(x) Hyperbolic arc tangent of x (in radians) + sqrt(x) Square root of x. Result is NaN (Not a Number) if x is negative. + log(x) Natural logarithm of x (not base-10). It’s log instead of ln because that’s what JavaScript calls it. + abs(x) Absolute value (magnatude) of x + ceil(x) Ceiling of x — the smallest integer that’s >= x. + floor(x) Floor of x — the largest integer that’s <= x. + round(x, n) X, rounded to the nearest integer or to n decimal places, using “gradeschool rounding”. + trunc(x) Integral part of a X, looks like floor(x) unless for negative number. + exp(x) ex (exponential/antilogarithm function with base e) Pre-defined functions Besides the “operator” functions, there are several pre-defined functions. You can provide your own, by binding variables to normal JavaScript functions. diff --git a/parser.js b/parser.js index a2d5b81..49ccf15 100644 --- a/parser.js +++ b/parser.js @@ -411,6 +411,42 @@ var Parser = (function (scope) { return val.toString().length; } + /** + * Decimal adjustment of a number. + * + * @param {String} type The type of adjustment. + * @param {Number} value The number. + * @param {Integer} exp The exponent (the 10 logarithm of the adjustment base). + * @return {Number} The adjusted value. + */ + function decimalAdjust(type, value, exp) { + // If the exp is undefined or zero... + if (typeof exp === 'undefined' || +exp === 0) { + return Math[type](value); + } + value = +value; + exp = -(+exp); + // If the value is not a number or the exp is not an integer... + if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) { + return NaN; + } + // Shift + value = value.toString().split('e'); + value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp))); + // Shift back + value = value.toString().split('e'); + return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)); + } + + function round(value, exp) { + // it comes as an array for some reason + if (value instanceof Array) { + exp = value[1] + value = value[0]; + } + return decimalAdjust('round', value, exp); + } + function append(a, b) { if (Object.prototype.toString.call(a) != "[object Array]") { return [a, b]; @@ -452,7 +488,7 @@ var Parser = (function (scope) { "abs": Math.abs, "ceil": Math.ceil, "floor": Math.floor, - "round": Math.round, + "round": round, "trunc": trunc, "-": neg, "exp": Math.exp @@ -526,7 +562,7 @@ var Parser = (function (scope) { abs: Math.abs, ceil: Math.ceil, floor: Math.floor, - round: Math.round, + round: round, trunc: trunc, random: random, fac: fac, diff --git a/test/parserSpec.js b/test/parserSpec.js index 29431f4..883fb6a 100644 --- a/test/parserSpec.js +++ b/test/parserSpec.js @@ -195,6 +195,27 @@ describe("Parser", function() { expect(Parser.evaluate("len('string')")).to.equal(6); }); }); + + describe("#round()", function() { + it("round(663)", function() { + expect(Parser.evaluate("round(663)")).to.equal(663); + }); + it("round(663, 0)", function() { + expect(Parser.evaluate("round(663, 0)")).to.equal(663); + }); + it("round(662.79)", function() { + expect(Parser.evaluate("round(662.79)")).to.equal(663); + }); + it("round(662.79, 1)", function() { + expect(Parser.evaluate("round(662.79, 1)")).to.equal(662.8); + }); + it("round(54.1, -1)", function() { + expect(Parser.evaluate("round(54.1, -1)")).to.equal(50); + }); + it("round(-23.67, 1)", function() { + expect(Parser.evaluate("round(-23.67, 1)")).to.equal(-23.7); + }); + }); }); /* @todo