diff --git a/.travis.yml b/.travis.yml index 15812b4..8beb852 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,14 @@ language: node_js node_js: - - "5.0" + - "6" + - "5" - "4.2" - "0.12" - "0.10" - "0.8" before_install: - "npm install -g npm@next" - - "npm install -g mocha" + - "npm install -g mocha voc" - "npm install blanket" - "npm install coveralls mocha-lcov-reporter" after_success: diff --git a/Makefile b/Makefile index fb506df..ab0b883 100644 --- a/Makefile +++ b/Makefile @@ -2,56 +2,57 @@ LIB=frac REQS= ADDONS= AUXTARGETS= +HTMLLINT=index.html ULIB=$(shell echo $(LIB) | tr a-z A-Z) DEPS=$(LIB).md TARGET=$(LIB).js +FLOWTARGET=$(LIB).flow.js + +## Main Targets .PHONY: all -all: $(TARGET) $(AUXTARGETS) +all: $(TARGET) $(AUXTARGETS) ## Build library and auxiliary scripts $(TARGET) $(AUXTARGETS): %.js : %.flow.js - node -e 'process.stdout.write(require("fs").readFileSync("$<","utf8").replace(/^\s*\/\*:[^*]*\*\/\s*(\n)?/gm,"").replace(/\/\*:[^*]*\*\//gm,""))' > $@ + node -e 'process.stdout.write(require("fs").readFileSync("$<","utf8").replace(/^[ \t]*\/\*[:#][^*]*\*\/\s*(\n)?/gm,"").replace(/\/\*[:#][^*]*\*\//gm,""))' > $@ -$(LIB).flow.js: $(DEPS) +$(FLOWTARGET): $(DEPS) voc $^ .PHONY: clean -clean: - rm -f $(TARGET) +clean: ## Remove targets and build artifacts + rm -f $(TARGET) $(FLOWTARGET) +## JavaScript .PHONY: test mocha -test mocha: test.js +test mocha: test.js $(TARGET) ## Run JS test suite mocha -R spec -t 20000 .PHONY: lint -lint: $(TARGET) $(AUXTARGETS) - jshint --show-non-errors $(TARGET) $(AUXTARGETS) - jshint --show-non-errors package.json - jscs $(TARGET) $(AUXTARGETS) +lint: $(TARGET) $(AUXTARGETS) ## Run jshint and jscs checks + @jshint --show-non-errors $(TARGET) $(AUXTARGETS) + @jshint --show-non-errors package.json + @jshint --show-non-errors --extract=always $(HTMLLINT) + @jscs $(TARGET) $(AUXTARGETS) .PHONY: flow -flow: lint - flow check --all --show-all-errors +flow: lint ## Run flow checker + @flow check --all --show-all-errors -.PHONY: cov cov-spin -cov: misc/coverage.html -cov-spin: - make cov & bash misc/spin.sh $$! +.PHONY: cov +cov: misc/coverage.html ## Run coverage test misc/coverage.html: $(TARGET) test.js mocha --require blanket -R html-cov -t 20000 > $@ -.PHONY: coveralls coveralls-spin -coveralls: - mocha --require blanket --reporter mocha-lcov-reporter -t 20000 | ./node_modules/coveralls/bin/coveralls.js - -coveralls-spin: - make coveralls & bash misc/spin.sh $$! +.PHONY: coveralls +coveralls: ## Coverage Test + Send to coveralls.io + mocha --require blanket --reporter mocha-lcov-reporter -t 20000 | node ./node_modules/coveralls/bin/coveralls.js .PHONY: dist -dist: dist-deps $(TARGET) +dist: dist-deps $(TARGET) ## Prepare JS files for distribution cp $(TARGET) dist/ cp LICENSE dist/ uglifyjs $(TARGET) -o dist/$(LIB).min.js --source-map dist/$(LIB).min.map --preamble "$$(head -n 1 frac.js)" @@ -65,16 +66,24 @@ dist-deps: ## Python .PHONY: pylint -pylint: frac.py $(wildcard test_*.py) +pylint: frac.py $(wildcard test_*.py) ## Run pep8 check pep8 $^ .PHONY: pypi -pypi: frac.py +pydist: frac.py ## Upload Python module to PyPI python setup.py sdist upload .PHONY: pytest pypytest -pytest: pylint +pytest: pylint ## Run Python test suite py.test -v --durations=5 -pypytest: pylint +pypytest: pylint ## Run Python test suite in pypy pypy $$(which py.test) -v --durations=5 + +.PHONY: help +help: + @grep -hE '(^[a-zA-Z_-][ a-zA-Z_-]*:.*?|^#[#*])' $(MAKEFILE_LIST) | bash misc/help.sh + +#* To show a spinner, append "-spin" to any target e.g. cov-spin +%-spin: + @make $* & bash misc/spin.sh $$! diff --git a/README.md b/README.md index ff856de..9fb959d 100644 --- a/README.md +++ b/README.md @@ -7,17 +7,22 @@ Uses the [Mediant Method](https://en.wikipedia.org/wiki/Mediant_method). This module also provides an implementation of the continued fraction method as described by Aberth in "A method for exact computation with rational numbers". + ## Installation ### JS With [npm](https://www.npmjs.org/package/frac): - $ npm install frac +```bash +$ npm install frac +``` In the browser: - +```html + +``` The script will manipulate `module.exports` if available (e.g. in a CommonJS `require` context). This is not always desirable. To prevent the behavior, @@ -27,7 +32,9 @@ define `DO_NOT_EXPORT_FRAC` From [PyPI](https://pypi.python.org/pypi/frac): - $ pip install frac +```bash +$ pip install frac +``` ## Usage @@ -67,33 +74,37 @@ For example: `frac.med` implements Mediant method. -`frac.cont` implements Aberth algorithm +`frac.cont` implements Aberth algorithm. For example: ```py >>> import frac ->>> frac.med(1.3, 9) # [ 0, 9, 7 ] ->>> frac.med(1.3, 9, True) # [ 1, 2, 7 ] ->>> frac.med(-1.3, 9) # [ 0, -9, 7 ] ->>> frac.med(-1.3, 9, True) # [ -2, 5, 7 ] +>>> frac.med(1.3, 9) ## [ 0, 9, 7 ] ## 1.3 ~ 9/7 +>>> frac.med(1.3, 9, True) ## [ 1, 2, 7 ] ## 1.3 ~ 1 + 2/7 +>>> frac.med(-1.3, 9) ## [ 0, -9, 7 ] ## -1.3 ~ -9/7 +>>> frac.med(-1.3, 9, True) ## [ -2, 5, 7 ] ## -1.3 ~ -2 + 5/7 ->>> frac.cont(1.3, 9) # [ 0, 4, 3 ] ->>> frac.cont(1.3, 9, True) # [ 1, 1, 3 ] ->>> frac.cont(-1.3, 9) # [ 0, -4, 3 ] ->>> frac.cont(-1.3, 9, True) # [ -2, 2, 3 ] +>>> frac.cont(1.3, 9) ## [ 0, 4, 3 ] ## 1.3 ~ 4/3 +>>> frac.cont(1.3, 9, True) ## [ 1, 1, 3 ] ## 1.3 ~ 1 + 1/3 +>>> frac.cont(-1.3, 9) ## [ 0, -4, 3 ] ## -1.3 ~ -4/3 +>>> frac.cont(-1.3, 9, True) ## [ -2, 2, 3 ] ## -1.3 ~ -2 + 2/3 ``` ## Testing -`make test` will run the node-based tests. - -Tests generated from Excel have 4 columns. To produce a similar test: +The test TSV baselines in the `test_files` directory have four columns: - Column A contains the raw values -- Column B format "Up to one digit (1/4)" -- Column C format "Up to two digits (21/25)" -- Column D format "Up to three digits (312/943)" +- Column B format "Up to one digit (1/4)" (`denominator = 9`) +- Column C format "Up to two digits (21/25)" (`denominator = 99`) +- Column D format "Up to three digits (312/943)" (`denominator = 999`) + +`make test` will run the node-based tests. + +`make pytest` will run the python tests against the system Python version. + +`make pypytest` will run the python tests against `pypy` if installed ## License diff --git a/dist/frac.js b/dist/frac.js index 9510e51..77f71d7 100644 --- a/dist/frac.js +++ b/dist/frac.js @@ -1,5 +1,5 @@ /* frac.js (C) 2012-present SheetJS -- http://sheetjs.com */ -var frac = function(x, D, mixed) { +var frac = function frac(x, D, mixed) { var n1 = Math.floor(x), d1 = 1; var n2 = n1+1, d2 = 1; if(x !== n1) while(d1 <= D && d2 <= D) { @@ -28,7 +28,7 @@ frac.cont = function cont(x, D, mixed) { A = Math.floor(B); P = A * P_1 + P_2; Q = A * Q_1 + Q_2; - if((B - A) < 0.000000005) break; + if((B - A) < 0.00000005) break; B = 1 / (B - A); P_2 = P_1; P_1 = P; Q_2 = Q_1; Q_1 = Q; diff --git a/dist/frac.min.js b/dist/frac.min.js index db508da..9a5cb02 100644 --- a/dist/frac.min.js +++ b/dist/frac.min.js @@ -1 +1,2 @@ -var frac=function(x,D,mixed){var n1=Math.floor(x),d1=1;var n2=n1+1,d2=1;if(x!==n1)while(d1<=D&&d2<=D){var m=(n1+n2)/(d1+d2);if(x===m){if(d1+d2<=D){d1+=d2;n1+=n2;d2=D+1}else if(d1>d2)d2=D+1;else d1=D+1;break}else if(xD){d1=d2;n1=n2}if(!mixed)return[0,n1,d1];var q=Math.floor(n1/d1);return[q,n1-q*d1,d1]};frac.cont=function cont(x,D,mixed){var sgn=x<0?-1:1;var B=x*sgn;var P_2=0,P_1=1,P=0;var Q_2=1,Q_1=0,Q=0;var A=Math.floor(B);while(Q_1D){if(Q_1>D){Q=Q_2;P=P_2}else{Q=Q_1;P=P_1}}if(!mixed)return[0,sgn*P,Q];var q=Math.floor(sgn*P/Q);return[q,sgn*P-q*Q,Q]};if(typeof module!=="undefined"&&typeof DO_NOT_EXPORT_FRAC==="undefined")module.exports=frac; +/* frac.js (C) 2012-present SheetJS -- http://sheetjs.com */ +var frac=function frac(x,D,mixed){var n1=Math.floor(x),d1=1;var n2=n1+1,d2=1;if(x!==n1)while(d1<=D&&d2<=D){var m=(n1+n2)/(d1+d2);if(x===m){if(d1+d2<=D){d1+=d2;n1+=n2;d2=D+1}else if(d1>d2)d2=D+1;else d1=D+1;break}else if(xD){d1=d2;n1=n2}if(!mixed)return[0,n1,d1];var q=Math.floor(n1/d1);return[q,n1-q*d1,d1]};frac.cont=function cont(x,D,mixed){var sgn=x<0?-1:1;var B=x*sgn;var P_2=0,P_1=1,P=0;var Q_2=1,Q_1=0,Q=0;var A=Math.floor(B);while(Q_1D){if(Q_1>D){Q=Q_2;P=P_2}else{Q=Q_1;P=P_1}}if(!mixed)return[0,sgn*P,Q];var q=Math.floor(sgn*P/Q);return[q,sgn*P-q*Q,Q]};if(typeof module!=="undefined"&&typeof DO_NOT_EXPORT_FRAC==="undefined")module.exports=frac; diff --git a/dist/frac.min.map b/dist/frac.min.map index 92894fe..b48688f 100644 --- a/dist/frac.min.map +++ b/dist/frac.min.map @@ -1 +1 @@ -{"version":3,"file":"dist/frac.min.js","sources":["frac.js"],"names":["frac","x","D","mixed","n1","Math","floor","d1","n2","d2","m","q","cont","sgn","B","P_2","P_1","P","Q_2","Q_1","Q","A","module","DO_NOT_EXPORT_FRAC","exports"],"mappings":"AACA,GAAIA,MAAO,SAASC,EAAGC,EAAGC,OACxB,GAAIC,IAAKC,KAAKC,MAAML,GAAIM,GAAK,CAC7B,IAAIC,IAAKJ,GAAG,EAAGK,GAAK,CACpB,IAAGR,IAAMG,GAAI,MAAMG,IAAML,GAAKO,IAAMP,EAAG,CACrC,GAAIQ,IAAKN,GAAKI,KAAOD,GAAKE,GAC1B,IAAGR,IAAMS,EAAG,CACV,GAAGH,GAAKE,IAAMP,EAAG,CAAEK,IAAIE,EAAIL,KAAII,EAAIC,IAAGP,EAAE,MACnC,IAAGK,GAAKE,GAAIA,GAAGP,EAAE,MACjBK,IAAGL,EAAE,CACV,WAEG,IAAGD,EAAIS,EAAG,CAAEF,GAAKJ,GAAGI,EAAIC,IAAKF,GAAGE,OAChC,CAAEL,GAAKA,GAAGI,EAAID,IAAKA,GAAGE,IAE7B,GAAGF,GAAKL,EAAG,CAAEK,GAAKE,EAAIL,IAAKI,GAC3B,IAAIL,MAAO,OAAQ,EAAGC,GAAIG,GAC1B,IAAII,GAAIN,KAAKC,MAAMF,GAAGG,GACtB,QAAQI,EAAGP,GAAKO,EAAEJ,GAAIA,IAExBP,MAAKY,KAAO,QAASA,MAAKX,EAAGC,EAAGC,OAC9B,GAAIU,KAAMZ,EAAI,GAAK,EAAI,CACvB,IAAIa,GAAIb,EAAIY,GACZ,IAAIE,KAAM,EAAGC,IAAM,EAAGC,EAAI,CAC1B,IAAIC,KAAM,EAAGC,IAAM,EAAGC,EAAI,CAC1B,IAAIC,GAAIhB,KAAKC,MAAMQ,EACnB,OAAMK,IAAMjB,EAAG,CACbmB,EAAIhB,KAAKC,MAAMQ,EACfG,GAAII,EAAIL,IAAMD,GACdK,GAAIC,EAAIF,IAAMD,GACd,IAAIJ,EAAIO,EAAK,KAAa,KAC1BP,GAAI,GAAKA,EAAIO,EACbN,KAAMC,GAAKA,KAAMC,CACjBC,KAAMC,GAAKA,KAAMC,EAEnB,GAAGA,EAAIlB,EAAG,CAAE,GAAGiB,IAAMjB,EAAG,CAAEkB,EAAIF,GAAKD,GAAIF,QAAY,CAAEK,EAAID,GAAKF,GAAID,KAClE,IAAIb,MAAO,OAAQ,EAAGU,IAAMI,EAAGG,EAC/B,IAAIT,GAAIN,KAAKC,MAAMO,IAAMI,EAAEG,EAC3B,QAAQT,EAAGE,IAAII,EAAIN,EAAES,EAAGA,GAE1B,UAAUE,UAAW,mBAAsBC,sBAAuB,YAAaD,OAAOE,QAAUxB"} \ No newline at end of file +{"version":3,"sources":["frac.js"],"names":["frac","x","D","mixed","n1","Math","floor","d1","n2","d2","m","q","cont","sgn","B","P_2","P_1","P","Q_2","Q_1","Q","A","module","DO_NOT_EXPORT_FRAC","exports"],"mappings":";AACA,GAAIA,MAAO,QAASA,MAAKC,EAAGC,EAAGC,OAC7B,GAAIC,IAAKC,KAAKC,MAAML,GAAIM,GAAK,CAC7B,IAAIC,IAAKJ,GAAG,EAAGK,GAAK,CACpB,IAAGR,IAAMG,GAAI,MAAMG,IAAML,GAAKO,IAAMP,EAAG,CACrC,GAAIQ,IAAKN,GAAKI,KAAOD,GAAKE,GAC1B,IAAGR,IAAMS,EAAG,CACV,GAAGH,GAAKE,IAAMP,EAAG,CAAEK,IAAIE,EAAIL,KAAII,EAAIC,IAAGP,EAAE,MACnC,IAAGK,GAAKE,GAAIA,GAAGP,EAAE,MACjBK,IAAGL,EAAE,CACV,WAEG,IAAGD,EAAIS,EAAG,CAAEF,GAAKJ,GAAGI,EAAIC,IAAKF,GAAGE,OAChC,CAAEL,GAAKA,GAAGI,EAAID,IAAKA,GAAGE,IAE7B,GAAGF,GAAKL,EAAG,CAAEK,GAAKE,EAAIL,IAAKI,GAC3B,IAAIL,MAAO,OAAQ,EAAGC,GAAIG,GAC1B,IAAII,GAAIN,KAAKC,MAAMF,GAAGG,GACtB,QAAQI,EAAGP,GAAKO,EAAEJ,GAAIA,IAExBP,MAAKY,KAAO,QAASA,MAAKX,EAAGC,EAAGC,OAC9B,GAAIU,KAAMZ,EAAI,GAAK,EAAI,CACvB,IAAIa,GAAIb,EAAIY,GACZ,IAAIE,KAAM,EAAGC,IAAM,EAAGC,EAAI,CAC1B,IAAIC,KAAM,EAAGC,IAAM,EAAGC,EAAI,CAC1B,IAAIC,GAAIhB,KAAKC,MAAMQ,EACnB,OAAMK,IAAMjB,EAAG,CACbmB,EAAIhB,KAAKC,MAAMQ,EACfG,GAAII,EAAIL,IAAMD,GACdK,GAAIC,EAAIF,IAAMD,GACd,IAAIJ,EAAIO,EAAK,KAAY,KACzBP,GAAI,GAAKA,EAAIO,EACbN,KAAMC,GAAKA,KAAMC,CACjBC,KAAMC,GAAKA,KAAMC,EAEnB,GAAGA,EAAIlB,EAAG,CAAE,GAAGiB,IAAMjB,EAAG,CAAEkB,EAAIF,GAAKD,GAAIF,QAAY,CAAEK,EAAID,GAAKF,GAAID,KAClE,IAAIb,MAAO,OAAQ,EAAGU,IAAMI,EAAGG,EAC/B,IAAIT,GAAIN,KAAKC,MAAMO,IAAMI,EAAEG,EAC3B,QAAQT,EAAGE,IAAII,EAAIN,EAAES,EAAGA,GAE1B,UAAUE,UAAW,mBAAsBC,sBAAuB,YAAaD,OAAOE,QAAUxB","file":"dist/frac.min.js"} \ No newline at end of file diff --git a/frac.flow.js b/frac.flow.js index aacbf10..7c8a745 100644 --- a/frac.flow.js +++ b/frac.flow.js @@ -1,5 +1,5 @@ /* frac.js (C) 2012-present SheetJS -- http://sheetjs.com */ -var frac = function(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array*/ { +var frac = function frac(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array*/ { var n1 = Math.floor(x), d1 = 1; var n2 = n1+1, d2 = 1; if(x !== n1) while(d1 <= D && d2 <= D) { @@ -28,7 +28,7 @@ frac.cont = function cont(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Arra A = Math.floor(B); P = A * P_1 + P_2; Q = A * Q_1 + Q_2; - if((B - A) < 0.000000005) break; + if((B - A) < 0.00000005) break; B = 1 / (B - A); P_2 = P_1; P_1 = P; Q_2 = Q_1; Q_1 = Q; diff --git a/frac.js b/frac.js index 9510e51..77f71d7 100644 --- a/frac.js +++ b/frac.js @@ -1,5 +1,5 @@ /* frac.js (C) 2012-present SheetJS -- http://sheetjs.com */ -var frac = function(x, D, mixed) { +var frac = function frac(x, D, mixed) { var n1 = Math.floor(x), d1 = 1; var n2 = n1+1, d2 = 1; if(x !== n1) while(d1 <= D && d2 <= D) { @@ -28,7 +28,7 @@ frac.cont = function cont(x, D, mixed) { A = Math.floor(B); P = A * P_1 + P_2; Q = A * Q_1 + Q_2; - if((B - A) < 0.000000005) break; + if((B - A) < 0.00000005) break; B = 1 / (B - A); P_2 = P_1; P_1 = P; Q_2 = Q_1; Q_1 = Q; diff --git a/frac.md b/frac.md index 410183b..f2802aa 100644 --- a/frac.md +++ b/frac.md @@ -23,7 +23,7 @@ that behavior, pass the absolute value to frac and prepend a "-" if negative. ```js>frac.flow.js /* frac.js (C) 2012-present SheetJS -- http://sheetjs.com */ -var frac = function(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array*/ { +var frac = function frac(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array*/ { ``` The goal is to maintain a feasible fraction (with bounded denominator) below @@ -91,7 +91,7 @@ to the desired goal of most accurately approximating the floating point number) frac.cont = function cont(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array*/ { ``` -> Record the sign of x, take b0=|x|, p_{-2}=0, p_{-1}=1, q_{-2}=1, q_{-1}=0 +> Record the sign of x, take `b0=|x|, p_{-2}=0, p_{-1}=1, q_{-2}=1, q_{-1}=0` Note that the variables are implicitly indexed at `k` (so `B` refers to `b_k`): @@ -102,8 +102,8 @@ Note that the variables are implicitly indexed at `k` (so `B` refers to `b_k`): var Q_2 = 1, Q_1 = 0, Q = 0; ``` -`A` should be the floor of `B`. Originally the bit-or trick was used, but this is not correct -for the range `B>=2**32`. +`A` should be the floor of `B`. Originally the bit-or trick was used, but this +is not correct for the range `B>=2**32`. ``` var A = Math.floor(B); @@ -111,31 +111,31 @@ for the range `B>=2**32`. > Iterate -> ... for k = 0,1,...,K, where K is the first instance of k where -> either q_{k+1} > Q or b_{k+1} is undefined (b_k = a_k). +> ... for `k = 0,1,...,K`, where `K` is the first instance of `k` where +> either `q_{k+1} > Q` or `b_{k+1}` is undefined (`b_k = a_k`). ``` while(Q_1 < D) { ``` -> a_k = [b_k], i.e., the greatest integer <= b_k +> `a_k = [b_k]`, i.e., the greatest integer `<= b_k` ``` A = Math.floor(B); ``` -> p_k = a_k p_{k-1} + p_{k-2} -> q_k = a_k q_{k-1} + q_{k-2} +> `p_k = a_k p_{k-1} + p_{k-2}` +> `q_k = a_k q_{k-1} + q_{k-2}` ``` P = A * P_1 + P_2; Q = A * Q_1 + Q_2; ``` -> b_{k+1} = (b_{k} - a_{k})^{-1} +> `b_{k+1} = (b_{k} - a_{k})^{-1}` ``` - if((B - A) < 0.000000005) break; + if((B - A) < 0.00000005) break; ``` At the end of each iteration, advance `k` by one step: @@ -184,21 +184,25 @@ var xltestfiles=[ ]; function xlline(o,j,m,w) { - it(j, function() { - var d, q, qq; + it(j.toString(), function() { + var d, q, qq, f = 0.1; + var q0 = 0, q1 = 0, q2 = 0 for(var i = j*w; i < m-3 && i < (j+1)*w; ++i) { d = o[i].split("\t"); + if(d.length < 3) continue; + f = parseFloat(d[0]); - q = frac.cont(Number(d[0]), 9, true); - qq = (q[0]||q[1]) ? (q[0] || "") + " " + (q[1] ? q[1] + "/" + q[2] : " ") : "0 "; + q = frac.cont(f, 9, true); + q0 = q[0]; q1 = q[1]; q2 = q[2]; + qq = (q0!=0||q1!=0) ? (q0!=0 ? q0.toString() : "") + " " + (q1!=0 ? q1.toString() + "/" + q2.toString() : " ") : "0 "; assert.equal(qq, d[1], d[1] + " 1"); - q = frac.cont(Number(d[0]), 99, true); - qq = (q[0]||q[1]) ? (q[0] || "") + " " + (q[1] ? (q[1] < 10 ? " " : "") + q[1] + "/" + q[2] + (q[2]<10?" ":"") : " ") : "0 "; + q = frac.cont(f, 99, true); + qq = (q[0]!=0||q[1]!=0) ? (q[0]!=0 ? q[0].toString() : "") + " " + (q[1]!=0 ? (q[1] < 10 ? " " : "") + q[1].toString() + "/" + q[2].toString() + (q[2]<10?" ":"") : " ") : "0 "; assert.equal(qq, d[2], d[2] + " 2"); - q = frac.cont(Number(d[0]), 999, true); - qq = (q[0]||q[1]) ? (q[0] || "") + " " + (q[1] ? (q[1] < 100 ? " " : "") + (q[1] < 10 ? " " : "") + q[1] + "/" + q[2] + (q[2]<10?" ":"") + (q[2]<100?" ":""): " ") : "0 "; + q = frac.cont(f, 999, true); + qq = (q[0]!=0||q[1]!=0) ? (q[0]!=0 ? q[0].toString() : "") + " " + (q[1]!=0 ? (q[1] < 100 ? " " : "") + (q[1] < 10 ? " " : "") + q[1].toString() + "/" + q[2].toString() + (q[2]<10?" ":"") + (q[2]<100?" ":""): " ") : "0 "; assert.equal(qq, d[3], d[3] + " 3"); } }); @@ -239,7 +243,7 @@ xltestfiles.forEach(function(x) { ```json>package.json { "name": "frac", - "version": "1.0.4", + "version": "1.0.5", "author": "SheetJS", "description": "Rational approximation with bounded denominator", "keywords": [ "math", "fraction", "rational", "approximation" ], @@ -252,7 +256,7 @@ xltestfiles.forEach(function(x) { }, "repository": { "type":"git", "url":"git://github.com/SheetJS/frac.git" }, "scripts": { - "test": "mocha -R spec" + "test": "make test" }, "config": { "blanket": { diff --git a/frac.py b/frac.py index 4625d2b..356442b 100644 --- a/frac.py +++ b/frac.py @@ -55,7 +55,7 @@ def cont(x, D, mixed=False): A = I(B) P = A * P_1 + P_2 Q = A * Q_1 + Q_2 - if (B - A) < 0.0000000005: + if (B - A) < 0.00000005: break B = 1. / (B-A) P_2, P_1 = P_1, P diff --git a/index.html b/index.html index 2b149e1..6b1d8a1 100644 --- a/index.html +++ b/index.html @@ -21,6 +21,7 @@