Skip to content

Commit

Permalink
Merge pull request #2 from javiercejudo/fractional
Browse files Browse the repository at this point in the history
feat: add support for fractional numbers
  • Loading branch information
javiercejudo committed Feb 28, 2016
2 parents 1c868c1 + 7eb3ea0 commit 15b7702
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 43 deletions.
18 changes: 14 additions & 4 deletions README.md
Expand Up @@ -25,21 +25,32 @@ hexToBin('1E'); //=> '11110'

See [spec](test/spec.js).

## Fractional support (including bases)

```js
bc(9, '11.08'); //=> '10.098765432098766'
```

See in [wolfram|Alpha](https://www.wolframalpha.com/input/?i=convert+11.08_9+to+base10).

```js
bc(3.145, '100.01'); //=> '9.992126756390263'
```

See in [wolfram|Alpha](https://www.wolframalpha.com/input/?i=convert+100.01+from+base+3.145+to+base10).

## Custom symbols

For any bases above 62, custom symbols are required.
See [tests](test/bigint-base-converter.js) for working examples.

```js
var bc = require('base-conversion-from-dec');

bc.symbols('⓿①②③④⑤⑥⑦⑧⑨ⒶⒷ', 12, '⑥①'); //=> '⑦③'
```

## Arbitrary precision

```js
var bc = require('base-conversion-to-dec');
var Big = require('arbitrary-precision')(require('bigjs-adapter'));
var toBigFactory = require('to-decimal-arbitrary-precision');

Expand All @@ -55,7 +66,6 @@ bc.big(d, 9, '802531310452364303450750087576673257456135727727');
## Full raw version

```js
var bc = require('base-conversion-to-dec');
var Big = require('arbitrary-precision')(require('bigjs-adapter'));
var toBigFactory = require('to-decimal-arbitrary-precision');

Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -44,6 +44,7 @@
"positional-notation": "^2.0.0",
"pow-arbitrary-precision": "^2.1.0",
"ramda": "^0.19.1",
"string-translate": "^1.1.1",
"times-arbitrary-precision": "^1.1.0",
"to-decimal-arbitrary-precision": "^1.0.2"
}
Expand Down
2 changes: 1 addition & 1 deletion src/R.js
Expand Up @@ -5,13 +5,13 @@
module.exports = Object.freeze({
__: require('ramda/src/__'),
addIndex: require('ramda/src/addIndex'),
adjust: require('ramda/src/adjust'),
curryN: require('ramda/src/curryN'),
identical: require('ramda/src/identical'),
identity: require('ramda/src/identity'),
indexOf: require('ramda/src/indexOf'),
invoker: require('ramda/src/invoker'),
join: require('ramda/src/join'),
nth: require('ramda/src/nth'),
map: require('ramda/src/map'),
memoize: require('ramda/src/memoize'),
pipe: require('ramda/src/pipe'),
Expand Down
26 changes: 26 additions & 0 deletions src/U.js
@@ -0,0 +1,26 @@
/*jshint node:true */

'use strict';

var R = require('./R');

var add = R.invoker(1, 'plus');

module.exports = Object.freeze({
add: add,

indexOfSymbol: R.memoize(function(symbols) {
return R.memoize(R.indexOf(R.__, symbols));
}),

joinWithoutSep: R.join(''),
joinWithDot: R.join('.'),

splitByDot: R.split('.'),

sum: function(big) {
return R.reduce(add, big('0'));
},

toString: R.invoker(0, 'toString')
});
18 changes: 18 additions & 0 deletions src/algorithm.js
@@ -0,0 +1,18 @@
/*jshint node:true */

'use strict';

var toBigFactory = require('to-decimal-arbitrary-precision');

var R = require('./R');
var U = require('./U');

var toDecimalRaw = R.curryN(5, function(mapper, big, symbols, base, n) {
return R.pipe(
R.map(U.indexOfSymbol(symbols)),
R.addIndex(R.map)(mapper(big, base)),
U.sum(big)
)(n);
});

module.exports = toDecimalRaw;
11 changes: 11 additions & 0 deletions src/fracMapper.js
@@ -0,0 +1,11 @@
/*jshint node:true */

'use strict';

var posNotation = require('positional-notation');

var R = require('./R');

module.exports = R.curryN(4, function(big, base, val, index) {
return posNotation.raw(big, base, [-index - 1, val]);
});
51 changes: 17 additions & 34 deletions src/index.js
Expand Up @@ -6,51 +6,34 @@ var posNotation = require('positional-notation');
var toBigFactory = require('to-decimal-arbitrary-precision');

var R = require('./R');
var U = require('./U');
var toDecimalAlg = require('./algorithm');
var fracMapper = require('./fracMapper');
var translate = require('./translate');

var defaultB = toBigFactory(require('./Big'));
var defaultBig = toBigFactory(require('./Big'));
var defaultSymbols = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
var joinWithoutSep = R.join('');
var splitWithoutSep = R.split('');
var toString = R.invoker(0, 'toString');
var add = R.invoker(1, 'plus');

var indexOfSymbol = R.memoize(function(symbols) {
return R.memoize(R.indexOf(R.__, symbols));
});

var nthSymbol = R.memoize(function(symbols) {
return R.memoize(R.nth(R.__, symbols));
});

var postprocess = R.memoize(function(symbols) {
return R.identical(symbols, defaultSymbols) ?
R.identity :
R.pipe(
R.map(nthSymbol(symbols)),
joinWithoutSep,
toString
);
});

var toDecimalRaw = R.curryN(4, function(b, symbols, base, n) {
var toDecimalRaw = R.curryN(4, function(big, symbols, base, n) {
return R.pipe(
toString,
R.reverse,
R.map(indexOfSymbol(symbols)),
R.addIndex(R.map)(posNotation.mapper(b, base)),
R.reduce(add, b(0)),
toString,
postprocess(symbols)
U.toString,
U.splitByDot,
R.adjust(R.reverse, 0),
R.adjust(toDecimalAlg(posNotation.mapper, big, symbols, base), 0),
R.adjust(toDecimalAlg(fracMapper, big, symbols, base), 1),
U.sum(big),
U.toString,
translate(defaultSymbols, symbols)
)(n);
});

var toDecimal = toDecimalRaw(defaultB, defaultSymbols);
var toDecimal = toDecimalRaw(defaultBig, defaultSymbols);

toDecimal.big = toDecimalRaw(R.__, defaultSymbols);
toDecimal.symbols = toDecimalRaw(defaultB);
toDecimal.symbols = toDecimalRaw(defaultBig);
toDecimal.raw = toDecimalRaw;

toDecimal.defaultSymbols = defaultSymbols;
toDecimal.defaultB = defaultB;
toDecimal.defaultBig = defaultBig;

module.exports = toDecimal;
11 changes: 11 additions & 0 deletions src/translate.js
@@ -0,0 +1,11 @@
/*jshint node:true */

'use strict';

var tr = require('string-translate');

var R = require('./R');

module.exports = R.memoize(function(defaultSymbols, symbols) {
return R.identical(defaultSymbols, symbols) ? R.identity : tr(defaultSymbols, symbols);
});
8 changes: 8 additions & 0 deletions test/integer-base-converter.js
Expand Up @@ -19,4 +19,12 @@ describe('integer-base-converter', function() {
.should.be.exactly(other.convert('Gf', 60, 10).toString())
.and.exactly(b60To10('Gf'));
});

it.skip('yields the same results for fractionals from base 60', function() {
var b60To10 = fn(60);

'3.14159'
.should.be.exactly(other.convert('3.8ThQO', 60, 10).toString())
.and.exactly(b60To10('3.8ThQO'));
});
});
24 changes: 20 additions & 4 deletions test/spec.js
Expand Up @@ -10,14 +10,14 @@ var toBigFactory = require('to-decimal-arbitrary-precision');
var fn = require('../src/');

describe('base conversion', function() {
it('base 62 to decimal', function() {
it('should support base 62 to decimal', function() {
var decTo62 = fn(62);

decTo62('y').should.be.exactly('60');
decTo62('11').should.be.exactly('63');
});

it('large base 9 to decimal', function() {
it('should support large base 9 to decimal', function() {
var d = toBigFactory(Big);

Big.Impl.E_POS = 50;
Expand All @@ -39,7 +39,23 @@ describe('base conversion', function() {
.should.be.exactly('#678364#6#34#634#634#63467#7364#63#34#3464#74#');
});

it.skip('non-integer from base 9', function() {
fn(9, '11.08').should.be.exactly('10.10');
it('should supportnon-integer from binary', function() {
fn.symbols('⓿①②③④⑤⑥⑦⑧⑨', 2, '①⓿⓿①.①⓿①')
.should.be.exactly('⑨.⑥②⑤');
});

it('should support non-integer from base 60', function() {
fn(60, '3.8ThQO')
.should.be.exactly('3.14159');
});

it('should support non-integer from base 9', function() {
fn(9, '11.08')
.should.be.exactly('10.098765432098766');
});

it('should support non-integer from non-integer base 3.145', function() {
fn(3.145, '100.01')
.should.be.exactly('9.992126756390263');
});
});

0 comments on commit 15b7702

Please sign in to comment.