Skip to content

Commit

Permalink
Remove decimals from digits
Browse files Browse the repository at this point in the history
  • Loading branch information
uellenberg committed May 2, 2021
1 parent 415408a commit 7ed5bcb
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 122 deletions.
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,5 @@
"nyc": "^15.1.0",
"typescript": "^4.2.4"
},
"dependencies": {
"parselib": "^1.0.0"
}
"dependencies": {}
}
18 changes: 7 additions & 11 deletions src/NumberTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
* @param num {number} - is the number which will be split.
* @constructor
*/
import {Digit} from "./types/Digit";

export const SplitNumber = (num: number) : SplitNumber => {
const split = num.toString().split(".");

Expand All @@ -30,13 +28,11 @@ export interface SplitNumber {
* Converts a digit to a number
* @param digit {Digit} - the digit being converted.
*/
export const DigitToNumber = (digit: Digit) : number => {
export const DigitToNumber = (digit: string) : number => {
//Essentially, the way this works is that if the number is not an integer, then it is the character code - 87. This is because character code 97 (a) is the first character code for 10.

let num = parseInt(digit.number);
if(isNaN(num)) num = digit.number.charCodeAt(0) - 87;

if(digit.decimals) num += digit.decimals/Math.pow(10, digit.decimals.toString().length);
let num = parseInt(digit);
if(isNaN(num)) num = digit.charCodeAt(0) - 87;

return num;
}
Expand All @@ -46,12 +42,12 @@ export const DigitToNumber = (digit: Digit) : number => {
* @param num {number} - the number that will be changed to a Digit.
* @constructor
*/
export const NumberToDigit = (num: number) : Digit => {
export const NumberToDigit = (num: number) : string => {
//This is similar to the above, but in reverse.

const split = SplitNumber(num);

return num < 10 ? {number: split.digits, decimals: split.decimals ? parseInt(split.decimals) : null} : {number: String.fromCharCode(parseInt(split.digits)+87), decimals: split.decimals ? parseInt(split.decimals) : null};
return num < 10 ? split.digits : String.fromCharCode(parseInt(split.digits)+87);
}

/**
Expand All @@ -69,8 +65,8 @@ export const FractionToBase = (fraction: number, base: number, precision: number
const num = Math.floor((fraction * Math.pow(base, tries+1)) % base);
let digit = NumberToDigit(num);

if(digit.number !== "0") {
digits.push(...toAdd, digit.number);
if(digit !== "0") {
digits.push(...toAdd, digit);
toAdd = [];
} else {
toAdd.push("0");
Expand Down
1 change: 0 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export {Num} from "./types/Num";
export {Digit} from "./types/Digit";
export {NumOptions} from "./types/NumOptions";
14 changes: 0 additions & 14 deletions src/types/Digit.ts

This file was deleted.

93 changes: 28 additions & 65 deletions src/types/Num.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import {Digit} from "./Digit";
import {DigitToNumber, FractionToBase, NumberToDigit, SplitNumber} from "../NumberTools";
import {NumOptions} from "./NumOptions";
import {RecursiveMap, RegexTokenizer, TokenizerChain} from "parselib";

const inputParseChain = new TokenizerChain(new RegexTokenizer(/[\[\]]/g));

/**
* A class providing information about a number.
Expand All @@ -26,14 +22,14 @@ export class Num {
* For example, in the number `1234.56`, this will contain the digits `1234`.
* @private
*/
private readonly _digits: Digit[] = [];
private readonly _digits: string[] = [];

/**
* The decimal digits of a number.
* For example, in the number `1234.56`, this will contain the digit `56`.
* @private
*/
private readonly _decimals: Digit[] = [];
private readonly _decimals: string[] = [];

/**
* A cache of all conversions to other number systems.
Expand Down Expand Up @@ -61,60 +57,23 @@ export class Num {

this._base = num.base;

let inputSplit = num.num.split(/\.(?![^[]*?])/g);
let inputSplit = num.num.split(/\./g);

const decimals = inputSplit.length > 1 ? inputSplit.pop() : "";
const digits = inputSplit.join(".") || "0";

const tokens = inputParseChain.run(digits);
const parsedDigits = RecursiveMap<Digit>(tokens, token => token.isToken && token.value === "[", token => token.isToken && token.value === "]", token => {
const digitSplit = token.value.split(".");

const number = digitSplit.shift() || "0";
const decimals = digitSplit.shift();

if(number.length > 1){
let out: Digit[] = [];

for(const digit of number){
out.push({number: digit});
}

return out;
}

return {number, decimals};
}, tokens => tokens, tokens => {
let out: Digit[] = [];

tokens.forEach(token => {
if(Array.isArray(token)) out.push(...token);
else out.push(token);
});

return out;
});
const digits = (inputSplit.join(".") || "0").split("");

let convertedNum = 0;

for (let i = 0; i < parsedDigits.length; i++) {
convertedNum += DigitToNumber({number: parsedDigits[i].number}) * Math.pow(this._base, parsedDigits.length-i-1);

if(parsedDigits[i].decimals){
const decimals1 = parsedDigits[i].decimals.toString();

for (let y = 0; y < decimals1.length; y++) {
convertedNum += DigitToNumber({number: decimals1[y]})/Math.pow(this._base, y+1)*Math.pow(this._base, parsedDigits.length-i-1);
}
}
for (let i = 0; i < digits.length; i++) {
convertedNum += DigitToNumber(digits[i]) * Math.pow(this._base, digits.length-i-1);
}

if(decimals){
for (let y = 0; y < decimals.length; y++) {
convertedNum += DigitToNumber({number: decimals[y]})/Math.pow(this._base, y+1);
convertedNum += DigitToNumber(decimals[y])/Math.pow(this._base, y+1);
}
}

return new Num({num: convertedNum});
} else {
if(typeof(num.num) === "string"){
Expand All @@ -128,12 +87,12 @@ export class Num {
const split = SplitNumber(num.num);

for (let digit of split.digits) {
this._digits.push({number: digit});
this._digits.push(digit);
}

if(split.decimals){
for (let decimal of split.decimals) {
this._decimals.push({number: decimal});
this._decimals.push(decimal);
}
}
}
Expand All @@ -148,33 +107,37 @@ export class Num {
private Convert(base: number, precision: number) : void {
if(this._cache.hasOwnProperty(base.toString() + "|" + precision.toString())) return;

const digit = parseInt(this._digits.map(digit => digit.number).join(""));
if(base === 10){
let digitsPart = this._digits.join("");
let decimalsPart = this._decimals.join("");

if(decimalsPart === "0") decimalsPart = "";

this._cache[base.toString() + "|" + precision.toString()] = digitsPart + (decimalsPart ? "." : "") + decimalsPart;

return;
}

let digit = parseInt(this._digits.join(""));
const digitLog = Math.ceil(Math.log(digit)/Math.log(this._base)) + (digit % this._base === 0 ? 1 : 0);

let digits: string[] = [];
let decimals: string[] = [];

for (let i = 0; i < digitLog; i++){
const number = Math.floor(digit/Math.pow(this._base, i)) % this._base;
const d = NumberToDigit(number);
for (let i = digitLog-1; i > -1; i--){
let number = Math.floor((digit / Math.pow(this._base, i)) % this._base);
digit -= number * Math.pow(this._base, i);

let str = d.number;
if(d.decimals) {
str = "["+(str !== "0" ? str : "")+"."+FractionToBase(d.decimals / Math.pow(10, d.decimals.toString().length), this._base, precision).join("")+"]";
}

digits.push(str);
digits.push(NumberToDigit(number));
}

digits.reverse();

if(this._base !== 10) {
let fraction = parseInt(this._decimals.map(decimal => decimal.number).join("")) / Math.pow(10, this._decimals.length);
let fraction = parseInt(this._decimals.join("")) / Math.pow(10, this._decimals.length);

decimals.push(...FractionToBase(fraction, this._base, precision));
} else {
for (let decimal of this._decimals) {
decimals.push(decimal.number);
decimals.push(decimal);
}
}

Expand Down
35 changes: 12 additions & 23 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,12 @@ describe("Num", () => {
expect(new Num(100.1)).to.eql({
_base: 10, _cache: {}, _digits:
[
{
number: "1"
},
{
number: "0"
},
{
number: "0"
}
"1",
"0",
"0"
],
_decimals: [
{
number: "1"
}
"1"
]
});
});
Expand All @@ -39,9 +31,9 @@ describe("Num", () => {

context("with number to base 2.5", () => {
it("should return the correct Num.", () => {
expect(new Num(9.5).ToBase(2.5).toString()).to.eql("1[.100212][1.100212].100212");
expect(new Num(9.5).ToBase(2.5).toString()).to.eql("110.100212");

expect(new Num(9).ToBase(2.5).toString()).to.eql("1[.100212][1.100212]");
expect(new Num(9).ToBase(2.5).toString()).to.eql("110");
});
});

Expand All @@ -65,9 +57,9 @@ describe("Num", () => {
//this shouldn't be possible
context("with number to base 65536.65536", () => {
it("should return the correct Num.", () => {
expect(new Num(5477458767.436).ToBase(65536.65536).toString()).to.eql("1[䛐.墑跢恎␄鏝庯保碷][趰.勀覴靧吧䒿箲뤯].濴ﮪ専祝㋟雏");
expect(new Num(5477458767.436).ToBase(65536.65536).toString()).to.eql("1䛐.濴ﮪ専祝㋟雏");

expect(new Num(5477458767).ToBase(65536.65536).toString()).to.eql("1[䛐.墑跢恎␄鏝庯保碷][趰.勀覴靧吧䒿箲뤯]");
expect(new Num(5477458767).ToBase(65536.65536).toString()).to.eql("1䛐");
});
});
});
Expand All @@ -84,14 +76,13 @@ describe("Num", () => {
context("with a base 2.5 number", () => {
it("should return the correct Num.", () => {
//9.5, some with inaccuracies
expect(new Num({num: "1[.100212][1.100212].100212", base: 2.5}).ToBase(10).toString()).to.eql("9.363343999999998");
expect(new Num({num: "110.100212", base: 2.5}).ToBase(10).toString()).to.eql("9.219631999999999");

//9, some with inaccuracies
expect(new Num({num: "1[.100212][1.100212]", base: 2.5}).ToBase(10).toString()).to.eql("8.893711999999999");
expect(new Num({num: "110", base: 2.5}).ToBase(10).toString()).to.eql("8.75");
});
});

//this is ridiculous
context("with a base 65536", () => {
it("should return the correct Num.", () => {
//I can't believe this actually worked
Expand All @@ -102,13 +93,11 @@ describe("Num", () => {
});
});

//this shouldn't be possible
context("with number to base 65536.65536", () => {
it("should return the correct Num.", () => {
//I am converting a number to base 65536.65536 and back to base 10 losslessly. How the hell?
expect(new Num({num: "1[䛐.墑跢恎␄鏝庯保碷][趰.勀覴靧吧䒿箲뤯].濴ﮪ専祝㋟雏", base: 65536.65536}).ToBase(10).toString()).to.eql("5477458767.436");
expect(new Num({num: "1䛐.濴ﮪ専祝㋟雏", base: 65536.65536}).ToBase(10).toString()).to.eql("5477458766.561177");

expect(new Num({num: "1[䛐.墑跢恎␄鏝庯保碷][趰.勀覴靧吧䒿箲뤯]", base: 65536.65536}).ToBase(10).toString()).to.eql("5477458767");
expect(new Num({num: "1䛐", base: 65536.65536}).ToBase(10).toString()).to.eql("5477458766.125177");
});
});
});
Expand Down
5 changes: 0 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1470,11 +1470,6 @@ parent-module@^1.0.0:
dependencies:
callsites "^3.0.0"

parselib@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/parselib/-/parselib-1.0.0.tgz#681a25a4614c75a8bb211b1786a90e33d1e48c02"
integrity sha512-G+pcgRKqcJKODRBJdIKxJh2IQPUUB4/HCNG0uAcubPg1pD1eFEHu66mNnF95jRW/Kv17nnzpeEi69gcWSWteRA==

path-exists@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
Expand Down

0 comments on commit 7ed5bcb

Please sign in to comment.