version bump 1.0.1: cleanup and python
- demo page (gh-pages branch) - updated year - flow annotations in separate frac.flow.js file - introduced build infrastructure from js-xlsx - python version
This commit is contained in:
parent
5ed8c61d24
commit
2f54d2f5c1
12
.flowconfig
Normal file
12
.flowconfig
Normal file
@ -0,0 +1,12 @@
|
||||
[ignore]
|
||||
.*/node_modules/.*
|
||||
.*/dist/.*
|
||||
.*/test.js
|
||||
.*/frac.js
|
||||
|
||||
[include]
|
||||
frac.flow.js
|
||||
|
||||
[libs]
|
||||
|
||||
[options]
|
6
.jscs.json
Normal file
6
.jscs.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"requireCommaBeforeLineBreak": true,
|
||||
"disallowTrailingWhitespace": true,
|
||||
"disallowTrailingComma": true
|
||||
}
|
||||
|
4
.jshintrc
Normal file
4
.jshintrc
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"bitwise": false,
|
||||
"curly": false
|
||||
}
|
11
.npmignore
11
.npmignore
@ -2,3 +2,14 @@ test_files/*.tsv
|
||||
.gitignore
|
||||
node_modules/
|
||||
coverage.html
|
||||
.travis.yml
|
||||
.jshintrc
|
||||
.jscs.json
|
||||
.flowconfig
|
||||
misc/
|
||||
*.sheetjs
|
||||
*.pyc
|
||||
build/
|
||||
MANIFEST
|
||||
*.gz
|
||||
*.tgz
|
||||
|
@ -1,5 +1,6 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "iojs"
|
||||
- "0.10"
|
||||
- "0.8"
|
||||
before_install:
|
||||
@ -7,4 +8,4 @@ before_install:
|
||||
- "npm install blanket"
|
||||
- "npm install coveralls mocha-lcov-reporter"
|
||||
after_success:
|
||||
- "make coveralls"
|
||||
- "make coveralls-spin"
|
||||
|
2
LICENSE
2
LICENSE
@ -1,4 +1,4 @@
|
||||
Copyright (C) 2012-2014 SheetJS
|
||||
Copyright (C) 2012-2015 SheetJS
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
77
Makefile
77
Makefile
@ -1,29 +1,74 @@
|
||||
LIB=frac
|
||||
TARGET=$(LIB).js
|
||||
.PHONY: frac
|
||||
frac: frac.md
|
||||
voc frac.md
|
||||
REQS=
|
||||
ADDONS=
|
||||
AUXTARGETS=
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
mocha -R spec
|
||||
ULIB=$(shell echo $(LIB) | tr a-z A-Z)
|
||||
DEPS=$(LIB).md
|
||||
TARGET=$(LIB).js
|
||||
|
||||
.PHONY: all
|
||||
all: $(TARGET) $(AUXTARGETS)
|
||||
|
||||
$(TARGET) $(AUXTARGETS): %.js : %.flow.js
|
||||
node -e 'process.stdout.write(require("fs").readFileSync("$<","utf8").replace(/^\s*\/\*:[^*]*\*\/\s*(\n)?/gm,"").replace(/\/\*:[^*]*\*\//gm,""))' > $@
|
||||
|
||||
$(LIB).flow.js: $(DEPS)
|
||||
voc $^
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f $(TARGET)
|
||||
|
||||
|
||||
.PHONY: test mocha
|
||||
test mocha: test.js
|
||||
mocha -R spec -t 20000
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
jshint --show-non-errors frac.js
|
||||
lint: $(TARGET) $(AUXTARGETS)
|
||||
jshint --show-non-errors $(TARGET) $(AUXTARGETS)
|
||||
jshint --show-non-errors package.json
|
||||
jscs $(TARGET) $(AUXTARGETS)
|
||||
|
||||
.PHONY: cov
|
||||
cov: coverage.html
|
||||
.PHONY: flow
|
||||
flow: lint
|
||||
flow check --all --show-all-errors
|
||||
|
||||
coverage.html: frac
|
||||
mocha --require blanket -R html-cov > coverage.html
|
||||
.PHONY: cov cov-spin
|
||||
cov: misc/coverage.html
|
||||
cov-spin:
|
||||
make cov & bash misc/spin.sh $$!
|
||||
|
||||
.PHONY: coveralls
|
||||
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 | ./node_modules/coveralls/bin/coveralls.js
|
||||
mocha --require blanket --reporter mocha-lcov-reporter -t 20000 | ./node_modules/coveralls/bin/coveralls.js
|
||||
|
||||
coveralls-spin:
|
||||
make coveralls & bash misc/spin.sh $$!
|
||||
|
||||
.PHONY: dist
|
||||
dist: $(TARGET)
|
||||
dist: dist-deps $(TARGET)
|
||||
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)"
|
||||
misc/strip_sourcemap.sh dist/$(LIB).min.js
|
||||
|
||||
.PHONY: aux
|
||||
aux: $(AUXTARGETS)
|
||||
.PHONY: dist-deps
|
||||
dist-deps:
|
||||
|
||||
## Python
|
||||
|
||||
.PHONY: pylint
|
||||
pylint: frac.py
|
||||
pep8 $^
|
||||
|
||||
.PHONY: pypi
|
||||
pypi: frac.py
|
||||
python setup.py sdist upload
|
||||
|
||||
|
1
README
Symbolic link
1
README
Symbolic link
@ -0,0 +1 @@
|
||||
README.md
|
36
README.md
36
README.md
@ -2,15 +2,14 @@
|
||||
|
||||
Rational approximation to a floating point number with bounded denominator.
|
||||
|
||||
Uses the Mediant Method <https://en.wikipedia.org/wiki/Mediant_(mathematics)>
|
||||
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",
|
||||
which appears to be used by spreadsheet programs for displaying fractions
|
||||
described by Aberth in "A method for exact computation with rational numbers".
|
||||
|
||||
## Setup
|
||||
## Installation
|
||||
|
||||
In node:
|
||||
With [npm](https://www.npmjs.org/package/frac):
|
||||
|
||||
$ npm install frac
|
||||
|
||||
@ -28,27 +27,28 @@ The exported `frac` function takes three arguments:
|
||||
|
||||
- `x` the number we wish to approximate
|
||||
- `D` the maximum denominator
|
||||
- `mixed` if true, return a mixed fraction (default); if false, improper
|
||||
- `mixed` if true, return a mixed fraction; if false, improper
|
||||
|
||||
The return value is an array of the form `[quot, num, den]` where `quot==0`
|
||||
for improper fractions.
|
||||
for improper fractions. `quot <= x` for mixed fractions, which may lead to some
|
||||
unexpected results when rendering negative numbers.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
> // var frac = require('frac'); // uncomment this line if in node
|
||||
> frac(Math.PI,100) // [ 0, 22, 7 ]
|
||||
> frac(Math.PI,100,true) // [ 3, 1, 7 ]
|
||||
> frac(Math.PI,100); // [ 0, 22, 7 ]
|
||||
> frac(Math.PI,100,true); // [ 3, 1, 7 ]
|
||||
> frac(-Math.PI,100); // [ 0, -22, 7 ]
|
||||
> frac(-Math.PI,100,true); // [ -4, 6, 7 ] // the approximation is (-4) + (6/7)
|
||||
```
|
||||
|
||||
`frac.cont` implements the Aberth algorithm (input and output specifications
|
||||
match the original `frac` function)
|
||||
|
||||
## License
|
||||
## Testing
|
||||
|
||||
Apache 2.0
|
||||
|
||||
## Tests
|
||||
`make test` will run the node-based tests.
|
||||
|
||||
Tests generated from Excel have 4 columns. To produce a similar test:
|
||||
|
||||
@ -57,9 +57,15 @@ Tests generated from Excel have 4 columns. To produce a similar test:
|
||||
- Column C format "Up to two digits (21/25)"
|
||||
- Column D format "Up to three digits (312/943)"
|
||||
|
||||
## License
|
||||
|
||||
Please consult the attached LICENSE file for details. All rights not explicitly
|
||||
granted by the Apache 2.0 license are reserved by the Original Author.
|
||||
|
||||
## Badges
|
||||
|
||||
[![Build Status](https://travis-ci.org/SheetJS/frac.svg?branch=master)](https://travis-ci.org/SheetJS/frac)
|
||||
|
||||
[![Coverage Status](https://coveralls.io/repos/SheetJS/frac/badge.png?branch=master)](https://coveralls.io/r/SheetJS/frac?branch=master)
|
||||
[![Coverage Status](http://img.shields.io/coveralls/SheetJS/frac/master.svg)](https://coveralls.io/r/SheetJS/frac?branch=master)
|
||||
|
||||
[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/731e31b3a26382ccd5d213b9e74ea552 "githalytics.com")](http://githalytics.com/SheetJS/frac)
|
||||
|
||||
|
2
dist/LICENSE
vendored
2
dist/LICENSE
vendored
@ -1,4 +1,4 @@
|
||||
Copyright (C) 2012-2014 SheetJS
|
||||
Copyright (C) 2012-2015 SheetJS
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
2
dist/frac.js
vendored
2
dist/frac.js
vendored
@ -1,4 +1,4 @@
|
||||
/* frac.js (C) 2012-2014 SheetJS -- http://sheetjs.com */
|
||||
/* frac.js (C) 2012-2015 SheetJS -- http://sheetjs.com */
|
||||
var frac = function(x, D, mixed) {
|
||||
var n1 = Math.floor(x), d1 = 1;
|
||||
var n2 = n1+1, d2 = 1;
|
||||
|
3
dist/frac.min.js
vendored
3
dist/frac.min.js
vendored
@ -1,3 +1,2 @@
|
||||
/* frac.js (C) 2012-2014 SheetJS -- http://sheetjs.com */
|
||||
/* frac.js (C) 2012-2015 SheetJS -- http://sheetjs.com */
|
||||
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(x<m){n2=n1+n2;d2=d1+d2}else{n1=n1+n2;d1=d1+d2}}if(d1>D){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_1<D){A=Math.floor(B);P=A*P_1+P_2;Q=A*Q_1+Q_2;if(B-A<5e-10)break;B=1/(B-A);P_2=P_1;P_1=P;Q_2=Q_1;Q_1=Q}if(Q>D){Q=Q_1;P=P_1}if(Q>D){Q=Q_2;P=P_2}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;
|
||||
//# sourceMappingURL=dist/frac.min.map
|
43
frac.flow.js
Normal file
43
frac.flow.js
Normal file
@ -0,0 +1,43 @@
|
||||
/* frac.js (C) 2012-2015 SheetJS -- http://sheetjs.com */
|
||||
var frac = function(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/ {
|
||||
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(x < m) { n2 = n1+n2; d2 = d1+d2; }
|
||||
else { n1 = n1+n2; d1 = d1+d2; }
|
||||
}
|
||||
if(d1 > D) { 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/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/ {
|
||||
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_1 < D) {
|
||||
A = Math.floor(B);
|
||||
P = A * P_1 + P_2;
|
||||
Q = A * Q_1 + Q_2;
|
||||
if((B - A) < 0.0000000005) break;
|
||||
B = 1 / (B - A);
|
||||
P_2 = P_1; P_1 = P;
|
||||
Q_2 = Q_1; Q_1 = Q;
|
||||
}
|
||||
if(Q > D) { Q = Q_1; P = P_1; }
|
||||
if(Q > D) { Q = Q_2; P = P_2; }
|
||||
if(!mixed) return [0, sgn * P, Q];
|
||||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
};
|
||||
/*:: declare var DO_NOT_EXPORT_FRAC: any; */
|
||||
if(typeof module !== 'undefined' && typeof DO_NOT_EXPORT_FRAC === 'undefined') module.exports = frac;
|
2
frac.js
2
frac.js
@ -1,4 +1,4 @@
|
||||
/* frac.js (C) 2012-2014 SheetJS -- http://sheetjs.com */
|
||||
/* frac.js (C) 2012-2015 SheetJS -- http://sheetjs.com */
|
||||
var frac = function(x, D, mixed) {
|
||||
var n1 = Math.floor(x), d1 = 1;
|
||||
var n2 = n1+1, d2 = 1;
|
||||
|
46
frac.md
46
frac.md
@ -4,20 +4,26 @@ In all languages, the target is a function that takes 3 parameters:
|
||||
|
||||
- `x` the number we wish to approximate
|
||||
- `D` the maximum denominator
|
||||
- `mixed` if true, return a mixed fraction (default); if false, improper
|
||||
- `mixed` if true, return a mixed fraction; if false, improper
|
||||
|
||||
The JS implementation walks through the algorithm.
|
||||
|
||||
# JS Implementation
|
||||
|
||||
In this version, the return value is `[quotient, numerator, denominator]`,
|
||||
where `quotient == 0` for improper fractions. The interpretation is
|
||||
`x ~ quotient + numerator / denominator` where `0 <= numerator < denominator`
|
||||
and `quotient <= x` for negative `x`.
|
||||
In this version, the return value is `[quotient, numerator, denominator]`. The
|
||||
interpretation is `x ~ quotient + numerator / denominator`
|
||||
|
||||
```js>frac.js
|
||||
/* frac.js (C) 2012-2014 SheetJS -- http://sheetjs.com */
|
||||
var frac = function(x, D, mixed) {
|
||||
- For improper fractions, `quotient == 0`.
|
||||
|
||||
- For proper fractions, `0 <= numerator < denominator` and `quotient <= x`
|
||||
|
||||
For negative `x`, this deviates from how some people and systems interpret mixed
|
||||
fractions. Some interpret `a b/c` as `sgn(a) * [abs(a) + b/c]`. To replicate
|
||||
that behavior, pass the absolute value to frac and prepend a "-" if negative.
|
||||
|
||||
```js>frac.flow.js
|
||||
/* frac.js (C) 2012-2015 SheetJS -- http://sheetjs.com */
|
||||
var frac = function(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/ {
|
||||
```
|
||||
|
||||
The goal is to maintain a feasible fraction (with bounded denominator) below
|
||||
@ -81,8 +87,8 @@ The continued fraction technique is employed by various spreadsheet programs.
|
||||
Note that this technique is inferior to the mediant method (at least, according
|
||||
to the desired goal of most accurately approximating the floating point number)
|
||||
|
||||
```
|
||||
frac.cont = function cont(x, D, mixed) {
|
||||
```js>frac.flow.js
|
||||
frac.cont = function cont(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/ {
|
||||
```
|
||||
|
||||
> Record the sign of x, take b0=|x|, p_{-2}=0, p_{-1}=1, q_{-2}=1, q_{-1}=0
|
||||
@ -160,6 +166,7 @@ The final result is `r = (sgn x)p_k / q_k`:
|
||||
Finally we put some export jazz:
|
||||
|
||||
```
|
||||
/*:: declare var DO_NOT_EXPORT_FRAC: any; */
|
||||
if(typeof module !== 'undefined' && typeof DO_NOT_EXPORT_FRAC === 'undefined') module.exports = frac;
|
||||
```
|
||||
|
||||
@ -234,7 +241,7 @@ xltestfiles.forEach(function(x) {
|
||||
```json>package.json
|
||||
{
|
||||
"name": "frac",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"author": "SheetJS",
|
||||
"description": "Rational approximation with bounded denominator",
|
||||
"keywords": [ "math", "fraction", "rational", "approximation" ],
|
||||
@ -267,6 +274,17 @@ test_files/*.tsv
|
||||
.gitignore
|
||||
node_modules/
|
||||
coverage.html
|
||||
.travis.yml
|
||||
.jshintrc
|
||||
.jscs.json
|
||||
.flowconfig
|
||||
misc/
|
||||
*.sheetjs
|
||||
*.pyc
|
||||
build/
|
||||
MANIFEST
|
||||
*.gz
|
||||
*.tgz
|
||||
```
|
||||
|
||||
Don't include the node modules in git:
|
||||
@ -275,4 +293,10 @@ Don't include the node modules in git:
|
||||
.gitignore
|
||||
node_modules/
|
||||
coverage.html
|
||||
*.sheetjs
|
||||
*.pyc
|
||||
build/
|
||||
MANIFEST
|
||||
*.gz
|
||||
*.tgz
|
||||
```
|
||||
|
73
frac.py
Normal file
73
frac.py
Normal file
@ -0,0 +1,73 @@
|
||||
# frac.py (C) 2015 SheetJS -- http://sheetjs.com
|
||||
# vim: set fileencoding=utf-8 :
|
||||
"""
|
||||
Rational approximations to numbers
|
||||
|
||||
This module can generate fraction representations using:
|
||||
- Mediant method (akin to fractions.Fraction#limit_denominator)
|
||||
- Aberth method (as used by spreadsheet software)
|
||||
|
||||
All functions take 3 arguments:
|
||||
|
||||
- x: the number to be approximated
|
||||
- D: the max denominator
|
||||
- mixed: if True, generate a mixed representation
|
||||
|
||||
The return value is a list of 3 elements: [quotient, numerator, denominator]
|
||||
"""
|
||||
|
||||
import math as Math
|
||||
|
||||
|
||||
def med(x, D, mixed=False):
|
||||
"""Generate fraction representation using Mediant method"""
|
||||
n1, d1 = int(Math.floor(x)), 1
|
||||
n2, d2 = n1+1, 1
|
||||
m = 0.
|
||||
if x != n1:
|
||||
while d1 <= D and d2 <= D:
|
||||
m = float(n1 + n2) / (d1 + d2)
|
||||
if(x == m):
|
||||
if d1 + d2 <= D:
|
||||
n1, d1 = n1 + n2, d1 + d2
|
||||
d2 = D + 1
|
||||
elif d1 > d2:
|
||||
d2 = D+1
|
||||
else:
|
||||
d1 = D+1
|
||||
break
|
||||
elif x < m:
|
||||
n2, d2 = n1+n2, d1+d2
|
||||
else:
|
||||
n1, d1 = n1+n2, d1+d2
|
||||
if d1 > D:
|
||||
n1, d1 = n2, d2
|
||||
if not mixed:
|
||||
return [0, n1, d1]
|
||||
q = divmod(n1, d1)
|
||||
return [q[0], q[1], d1]
|
||||
|
||||
|
||||
def cont(x, D, mixed=False):
|
||||
"""Generate fraction representation using Aberth method"""
|
||||
sgn = -1 if x < 0 else 1
|
||||
B = abs(x)
|
||||
P_2, P_1, P = 0, 1, 0
|
||||
Q_2, Q_1, Q = 1, 0, 0
|
||||
while Q_1 < D:
|
||||
A = int(Math.floor(B))
|
||||
P = A * P_1 + P_2
|
||||
Q = A * Q_1 + Q_2
|
||||
if ((B - A) < 0.0000000005):
|
||||
break
|
||||
B = 1. / (B-A)
|
||||
P_2, P_1 = P_1, P
|
||||
Q_2, Q_1 = Q_1, Q
|
||||
if(Q > D):
|
||||
P, Q = P_1, Q_1
|
||||
if(Q > D):
|
||||
P, Q = P_2, Q_2
|
||||
if not mixed:
|
||||
return [0, sgn * P, Q]
|
||||
q = divmod(sgn * P, Q)
|
||||
return [q[0], q[1], Q]
|
79
index.html
Normal file
79
index.html
Normal file
@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- frac.js (C) 2015 SheetJS http://sheetjs.com -->
|
||||
<!-- vim: set ts=2: -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Fraction Live Demo</title>
|
||||
<script src="frac.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<b>Fraction Live Demo</b><br />
|
||||
<a href="https://github.com/SheetJS/frac">Source Code</a><br />
|
||||
<a href="https://github.com/SheetJS/frac/issues">Issues? Something look weird? Click here and report an issue</a><br />
|
||||
<br />
|
||||
<table>
|
||||
<tr><td><b>Number:</b></td><td><input type="text" id="val" value="1.3"></td></tr>
|
||||
<tr><td><b>Denominator Digits:</b></td><td><input type="text" id="fmt" value="1"></td></tr>
|
||||
<tr><td><b>Use Mixed Fraction:</b></td><td><input type="checkbox" id="mix" name="mixd" checked></td></tr>
|
||||
<tr><td colspan="2"> </td></tr>
|
||||
<tr><td><b>Mediant Fraction:</b></td><td><pre id="frm"></pre></td></tr>
|
||||
<tr><td><b>Aberth Fraction:</b></td><td><pre id="fra"></pre></td></tr>
|
||||
</table>
|
||||
</body>
|
||||
<script>
|
||||
var V = document.getElementById('val');
|
||||
var F = document.getElementById('fmt');
|
||||
var X = document.getElementById('mix');
|
||||
var M = document.getElementById('frm');
|
||||
var A = document.getElementById('fra');
|
||||
|
||||
function update() {
|
||||
var x, D, mixed, oM, oA;
|
||||
x = Number(V.value);
|
||||
D = Math.pow(10, Number(F.value))-1;
|
||||
mixed = X.checked;
|
||||
if(x !== x) { M.innerHTML=A.innerHTML = V.value + " not valid"; return; }
|
||||
if(D !== D) { M.innerHTML=A.innerHTML = F.value + " not valid"; return; }
|
||||
try {
|
||||
oM = frac(x, D, mixed);
|
||||
M.innerHTML = oM[0] + " " + oM[1] + "/" + oM[2];
|
||||
} catch(e) { M.innerHTML = e.message; }
|
||||
try {
|
||||
oA = frac.cont(x, D, mixed);
|
||||
A.innerHTML = oA[0] + " " + oA[1] + "/" + oA[2];
|
||||
} catch(e) { A.innerHTML = e.message; }
|
||||
}
|
||||
|
||||
/* Bind to relevant events */
|
||||
if(F.addEventListener) {
|
||||
F.addEventListener('keyup', update);
|
||||
V.addEventListener('keyup', update);
|
||||
M.addEventListener('change', update);
|
||||
X.addEventListener('change', update);
|
||||
} else if(F.attachEvent) {
|
||||
F.attachEvent('onkeyup', update);
|
||||
V.attachEvent('onkeyup', update);
|
||||
M.attachEvent('onchange', update);
|
||||
X.attachEvent('onchange', update);
|
||||
} else {
|
||||
F.oninput = update;
|
||||
V.oninput = update;
|
||||
M.onchange = update;
|
||||
X.onchange = update;
|
||||
}
|
||||
|
||||
update();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-36810333-1']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
</html>
|
||||
|
14
misc/spin.sh
Executable file
14
misc/spin.sh
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
# spin.sh -- show a spinner (for coverage test)
|
||||
# Copyright (C) 2014-2015 SheetJS
|
||||
|
||||
wpid=$1
|
||||
delay=1
|
||||
str="|/-\\"
|
||||
while [ $(ps -a|awk '$1=='$wpid' {print $1}') ]; do
|
||||
t=${str#?}
|
||||
printf " [%c]" "$str"
|
||||
str=$t${str%"$t"}
|
||||
sleep $delay
|
||||
printf "\b\b\b\b"
|
||||
done
|
11
misc/strip_sourcemap.sh
Executable file
11
misc/strip_sourcemap.sh
Executable file
@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
# strip_sourcemap.sh -- strip sourcemaps from a JS file (missing from uglifyjs)
|
||||
# Copyright (C) 2014-2015 SheetJS
|
||||
|
||||
if [ $# -gt 0 ]; then
|
||||
if [ -e "$1" ]; then
|
||||
sed -i .sheetjs '/sourceMappingURL/d' "$1"
|
||||
fi
|
||||
else
|
||||
cat - | sed '/sourceMappingURL/d'
|
||||
fi
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "frac",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"author": "SheetJS",
|
||||
"description": "Rational approximation with bounded denominator",
|
||||
"keywords": [ "math", "fraction", "rational", "approximation" ],
|
||||
|
28
setup.py
Normal file
28
setup.py
Normal file
@ -0,0 +1,28 @@
|
||||
from distutils.core import setup
|
||||
setup(
|
||||
name='frac',
|
||||
version='0.0.1',
|
||||
author='SheetJS',
|
||||
author_email='dev@sheetjs.com',
|
||||
url='http://oss.sheetjs.com/frac',
|
||||
description='Rational approximations to numbers',
|
||||
long_description = """
|
||||
Rational approximations to numbers
|
||||
|
||||
This module can generate fraction representations using:
|
||||
- Mediant method (akin to fractions.Fraction#limit_denominator)
|
||||
- Aberth method (as used by spreadsheet software)
|
||||
""",
|
||||
platforms = ["any"],
|
||||
requires=[],
|
||||
py_modules=['frac'],
|
||||
scripts = [],
|
||||
license = "Apache-2.0",
|
||||
keywords = ['frac', 'fraction', 'rational', 'approximation'],
|
||||
classifiers = [
|
||||
'Development Status :: 3 - Alpha',
|
||||
'License :: OSI Approved :: Apache Software License',
|
||||
'Topic :: Office/Business',
|
||||
'Topic :: Utilities',
|
||||
]
|
||||
)
|
Loading…
Reference in New Issue
Block a user