pimath 0.0.64 → 0.0.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +23 -23
- package/dist/pi.js +236 -56
- package/dist/pi.js.map +1 -1
- package/dist/pi.min.js +1 -1
- package/dist/pi.min.js.map +1 -1
- package/docs/assets/highlight.css +78 -78
- package/docs/assets/main.js +52 -52
- package/docs/assets/style.css +1413 -1413
- package/docs/classes/Logicalset.Logicalset-1.html +4 -4
- package/docs/classes/Polynom.Rational.html +3 -3
- package/docs/classes/algebra_equation.Equation.html +25 -25
- package/docs/classes/algebra_monom.Monom.html +113 -113
- package/docs/classes/algebra_polynom.Polynom.html +29 -29
- package/docs/classes/coefficients_fraction.Fraction.html +18 -18
- package/docs/classes/coefficients_nthroot.NthRoot.html +2 -2
- package/docs/classes/geometry_circle.Circle.html +2 -2
- package/docs/classes/geometry_line.Line.html +2 -2
- package/docs/classes/geometry_triangle.Triangle.html +16 -16
- package/docs/classes/numeric.Numeric.html +13 -13
- package/docs/classes/shutingyard.Shutingyard.html +17 -17
- package/docs/index.html +10 -10
- package/docs/interfaces/algebra_equation.ISolution.html +2 -2
- package/docs/modules/Logicalset.html +2 -2
- package/docs/modules/Polynom.html +2 -2
- package/docs/modules/Vector.html +2 -2
- package/esm/maths/algebra/equation.js +2 -2
- package/esm/maths/algebra/equation.js.map +1 -1
- package/esm/maths/algebra/polynom.d.ts +4 -5
- package/esm/maths/algebra/polynom.js +2 -2
- package/esm/maths/algebra/polynom.js.map +1 -1
- package/esm/maths/algebra/rational.d.ts +8 -10
- package/esm/maths/algebra/rational.js +9 -5
- package/esm/maths/algebra/study/rationalStudy.d.ts +1 -2
- package/esm/maths/algebra/study/rationalStudy.js +32 -20
- package/esm/maths/algebra/study/rationalStudy.js.map +1 -1
- package/esm/maths/algebra/study.d.ts +16 -24
- package/esm/maths/algebra/study.js +65 -24
- package/esm/maths/algebra/study.js.map +1 -1
- package/esm/maths/coefficients/fraction.d.ts +8 -6
- package/esm/maths/coefficients/fraction.js +34 -17
- package/esm/maths/coefficients/fraction.js.map +1 -1
- package/esm/maths/expressions/expression.d.ts +21 -0
- package/esm/maths/expressions/expression.js +161 -0
- package/esm/maths/expressions/expression.js.map +1 -0
- package/esm/maths/expressions/expressionFactor.d.ts +29 -0
- package/esm/maths/expressions/expressionFactor.js +109 -0
- package/esm/maths/expressions/expressionFactor.js.map +1 -0
- package/esm/maths/expressions/expressionMember.d.ts +16 -0
- package/esm/maths/expressions/expressionMember.js +90 -0
- package/esm/maths/expressions/expressionMember.js.map +1 -0
- package/esm/maths/expressions/expressionOperators.d.ts +8 -0
- package/esm/maths/expressions/expressionOperators.js +42 -0
- package/esm/maths/expressions/expressionOperators.js.map +1 -0
- package/esm/maths/expressions/expressionParser.d.ts +12 -0
- package/esm/maths/expressions/expressionParser.js +219 -0
- package/esm/maths/expressions/expressionParser.js.map +1 -0
- package/esm/maths/expressions/factors/ExpFactor.d.ts +7 -0
- package/esm/maths/expressions/factors/ExpFactor.js +22 -0
- package/esm/maths/expressions/factors/ExpFactor.js.map +1 -0
- package/esm/maths/expressions/factors/ExpFactorConstant.d.ts +13 -0
- package/esm/maths/expressions/factors/ExpFactorConstant.js +49 -0
- package/esm/maths/expressions/factors/ExpFactorConstant.js.map +1 -0
- package/esm/maths/expressions/factors/ExpFactorExponential.d.ts +7 -0
- package/esm/maths/expressions/factors/ExpFactorExponential.js +18 -0
- package/esm/maths/expressions/factors/ExpFactorExponential.js.map +1 -0
- package/esm/maths/expressions/factors/ExpFactorNumber.d.ts +13 -0
- package/esm/maths/expressions/factors/ExpFactorNumber.js +36 -0
- package/esm/maths/expressions/factors/ExpFactorNumber.js.map +1 -0
- package/esm/maths/expressions/factors/ExpFactorPower.d.ts +9 -0
- package/esm/maths/expressions/factors/ExpFactorPower.js +22 -0
- package/esm/maths/expressions/factors/ExpFactorPower.js.map +1 -0
- package/esm/maths/expressions/factors/ExpFactorSin.d.ts +7 -0
- package/esm/maths/expressions/factors/ExpFactorSin.js +22 -0
- package/esm/maths/expressions/factors/ExpFactorSin.js.map +1 -0
- package/esm/maths/expressions/factors/ExpFactorTrigo.d.ts +19 -0
- package/esm/maths/expressions/factors/ExpFactorTrigo.js +40 -0
- package/esm/maths/expressions/factors/ExpFactorTrigo.js.map +1 -0
- package/esm/maths/expressions/factors/ExpFactorVariable.d.ts +12 -0
- package/esm/maths/expressions/factors/ExpFactorVariable.js +33 -0
- package/esm/maths/expressions/factors/ExpFactorVariable.js.map +1 -0
- package/esm/maths/expressions/internals.d.ts +12 -0
- package/esm/maths/expressions/internals.js +29 -0
- package/esm/maths/expressions/internals.js.map +1 -0
- package/esm/maths/shutingyard.d.ts +4 -1
- package/esm/maths/shutingyard.js +137 -21
- package/esm/maths/shutingyard.js.map +1 -1
- package/graph.svg +1033 -0
- package/package.json +1 -1
- package/src/maths/algebra/equation.ts +2 -2
- package/src/maths/algebra/polynom.ts +1 -0
- package/src/maths/algebra/study/rationalStudy.ts +26 -12
- package/src/maths/algebra/study.ts +48 -5
- package/src/maths/coefficients/fraction.ts +111 -86
- package/src/maths/expressions/expression.ts +191 -0
- package/src/maths/expressions/expressionFactor.ts +138 -0
- package/src/maths/expressions/expressionMember.ts +114 -0
- package/src/maths/expressions/expressionOperators.ts +49 -0
- package/src/maths/expressions/expressionParser.ts +249 -0
- package/src/maths/expressions/factors/ExpFactor.ts +26 -0
- package/src/maths/expressions/factors/ExpFactorConstant.ts +56 -0
- package/src/maths/expressions/factors/ExpFactorExponential.ts +19 -0
- package/src/maths/expressions/factors/ExpFactorNumber.ts +44 -0
- package/src/maths/expressions/factors/ExpFactorPower.ts +24 -0
- package/src/maths/expressions/factors/ExpFactorTrigo.ts +44 -0
- package/src/maths/expressions/factors/ExpFactorVariable.ts +40 -0
- package/src/maths/expressions/internals.ts +14 -0
- package/src/maths/shutingyard.ts +156 -26
- package/tests/algebra/study.test.ts +29 -4
- package/tests/coefficients/fraction.test.ts +17 -0
- package/tests/expressions/expressions.test.ts +124 -0
- package/tests/shutingyard.test.ts +22 -0
- package/.idea/shelf/Uncommitted_changes_before_Update_at_17_04_2022_12_40_[Changes]/shelved.patch +0 -21
- package/.idea/shelf/Uncommitted_changes_before_Update_at_17_04_2022_12_40__Changes_.xml +0 -4
package/package.json
CHANGED
|
@@ -576,9 +576,9 @@ export class Equation {
|
|
|
576
576
|
} else {
|
|
577
577
|
// Must handle the case if the m1 monom is negative.
|
|
578
578
|
if ((this.isGreater() && m1.sign() === 1) || (!this.isGreater() && m1.sign() === -1)) {
|
|
579
|
-
s = `\\left${this.isAlsoEqual() ? '\\[' : '\\]'}${v};+\\infty\\right\\[`;
|
|
579
|
+
s = `\\left${this.isAlsoEqual() ? '\\[' : '\\]'}${v.tex};+\\infty\\right\\[`;
|
|
580
580
|
} else {
|
|
581
|
-
s = `\\left\\]-\\infty;${v} \\right\\${this.isAlsoEqual() ? '\\]' : '\\['}`;
|
|
581
|
+
s = `\\left\\]-\\infty;${v.tex} \\right\\${this.isAlsoEqual() ? '\\]' : '\\['}`;
|
|
582
582
|
}
|
|
583
583
|
}
|
|
584
584
|
this._solutions = [{
|
|
@@ -259,6 +259,7 @@ export class Polynom {
|
|
|
259
259
|
this._factors = []
|
|
260
260
|
this.mark_as_dirty()
|
|
261
261
|
|
|
262
|
+
// TODO: allow to enter a liste of Fraction (a, b, c, ...) to make a polynom ax^n + bx^(n-1) + cx^(n-2) + ...
|
|
262
263
|
if (typeof inputStr === 'string') {
|
|
263
264
|
return this._parseString(inputStr, ...values)
|
|
264
265
|
} else if (
|
|
@@ -36,7 +36,6 @@ export class RationalStudy extends Study {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
makeZeroes(): IZero[] {
|
|
39
|
-
console.log('GETTING ZEROES')
|
|
40
39
|
return this._getZeroes(this.fx)
|
|
41
40
|
};
|
|
42
41
|
|
|
@@ -68,11 +67,13 @@ export class RationalStudy extends Study {
|
|
|
68
67
|
}
|
|
69
68
|
|
|
70
69
|
asymptotes.push({
|
|
70
|
+
fx: null,
|
|
71
71
|
type: Ztype,
|
|
72
72
|
tex: tex,
|
|
73
73
|
zero: zero,
|
|
74
74
|
limits: `\\lim_{x\\to${zero.tex} }\\ f(x) = \\pm\\infty`,
|
|
75
|
-
deltaX: null
|
|
75
|
+
deltaX: null,
|
|
76
|
+
tableOfSign: null
|
|
76
77
|
})
|
|
77
78
|
})
|
|
78
79
|
|
|
@@ -80,35 +81,45 @@ export class RationalStudy extends Study {
|
|
|
80
81
|
let NDegree = this.fx.numerator.degree(),
|
|
81
82
|
DDegree = this.fx.denominator.degree()
|
|
82
83
|
if (NDegree.isEqual(DDegree)) {
|
|
83
|
-
let H = this.fx.numerator.monomByDegree().coefficient.clone().divide(this.fx.denominator.monomByDegree().coefficient)
|
|
84
|
+
let H = this.fx.numerator.monomByDegree().coefficient.clone().divide(this.fx.denominator.monomByDegree().coefficient),
|
|
85
|
+
Htex = H.tex
|
|
86
|
+
|
|
87
|
+
let {reminder} = reduced.euclidian(),
|
|
88
|
+
deltaX = new Rational(reminder, reduced.denominator)
|
|
84
89
|
|
|
85
|
-
let {reminder} = reduced.euclidian()
|
|
86
90
|
|
|
87
91
|
asymptotes.push({
|
|
92
|
+
fx: new Polynom(H),
|
|
88
93
|
type: ASYMPTOTE.HORIZONTAL,
|
|
89
|
-
tex: `y=${
|
|
94
|
+
tex: `y=${Htex}`,
|
|
90
95
|
zero: null,
|
|
91
|
-
limits: `\\lim_{x\\to\\infty}\\ f(x) = ${
|
|
92
|
-
deltaX
|
|
96
|
+
limits: `\\lim_{x\\to\\infty}\\ f(x) = ${Htex}`,
|
|
97
|
+
deltaX,
|
|
98
|
+
tableOfSign: this._getSigns(deltaX)
|
|
93
99
|
})
|
|
94
100
|
} else if (DDegree.greater(NDegree)) {
|
|
95
101
|
asymptotes.push({
|
|
102
|
+
fx: new Polynom('0'),
|
|
96
103
|
type: ASYMPTOTE.HORIZONTAL,
|
|
97
104
|
tex: `y=0`,
|
|
98
105
|
zero: null,
|
|
99
106
|
limits: `\\lim_{x\\to\\infty}\\ f(x) = ${0}`,
|
|
100
|
-
deltaX: null
|
|
107
|
+
deltaX: null,
|
|
108
|
+
tableOfSign: null
|
|
101
109
|
})
|
|
102
110
|
} else if (NDegree.value - 1 === DDegree.value) {
|
|
103
111
|
// Calculate the slope
|
|
104
|
-
let {quotient, reminder} = reduced.euclidian()
|
|
112
|
+
let {quotient, reminder} = reduced.euclidian(),
|
|
113
|
+
deltaX = new Rational(reminder, reduced.denominator)
|
|
105
114
|
|
|
106
115
|
asymptotes.push({
|
|
116
|
+
fx: quotient.clone(),
|
|
107
117
|
type: ASYMPTOTE.SLOPE,
|
|
108
118
|
tex: `y=${quotient.tex}`,
|
|
109
119
|
zero: null,
|
|
110
120
|
limits: ``,
|
|
111
|
-
deltaX: new Rational(reminder, reduced.denominator)
|
|
121
|
+
deltaX: new Rational(reminder, reduced.denominator),
|
|
122
|
+
tableOfSign: this._getSigns(deltaX)
|
|
112
123
|
})
|
|
113
124
|
}
|
|
114
125
|
|
|
@@ -119,7 +130,6 @@ export class RationalStudy extends Study {
|
|
|
119
130
|
let dx = this.fx.clone().derivative(),
|
|
120
131
|
tos = this._getSigns(dx, this._getZeroes(dx), TABLE_OF_SIGNS.GROWS)
|
|
121
132
|
|
|
122
|
-
console.log(tos.factors.length, tos.signs.length)
|
|
123
133
|
let result = this.makeGrowsResult(tos)
|
|
124
134
|
tos.signs.push(result.growsLine)
|
|
125
135
|
tos.extremes = result.extremes
|
|
@@ -175,11 +185,15 @@ export class RationalStudy extends Study {
|
|
|
175
185
|
return zeroes
|
|
176
186
|
}
|
|
177
187
|
|
|
178
|
-
private _getSigns(fx: Rational, zeroes
|
|
188
|
+
private _getSigns(fx: Rational, zeroes?: IZero[], typeOfTable?: TABLE_OF_SIGNS): ITableOfSigns {
|
|
179
189
|
// Factorize the rational
|
|
180
190
|
let signs: (string[])[] = [],
|
|
181
191
|
factors: Polynom[] = []
|
|
182
192
|
|
|
193
|
+
if (zeroes === undefined) {
|
|
194
|
+
zeroes = this._getZeroes(fx)
|
|
195
|
+
}
|
|
196
|
+
|
|
183
197
|
fx.numerator.factors.forEach(factor => {
|
|
184
198
|
signs.push(this.makeOneLineForSigns(factor, zeroes, ZEROTYPE.ZERO))
|
|
185
199
|
factors.push(factor.clone())
|
|
@@ -8,6 +8,7 @@ import {ISolution} from "./equation";
|
|
|
8
8
|
import {Polynom} from "./polynom";
|
|
9
9
|
import {Fraction} from "../coefficients/fraction";
|
|
10
10
|
import {Point} from "../geometry/point";
|
|
11
|
+
import {NumExp} from "../expressions/numexp";
|
|
11
12
|
|
|
12
13
|
export type StudyableFunction = Rational
|
|
13
14
|
|
|
@@ -31,11 +32,13 @@ export enum ASYMPTOTE {
|
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export interface IAsymptote {
|
|
35
|
+
fx: Polynom,
|
|
34
36
|
deltaX: StudyableFunction
|
|
35
37
|
limits: string,
|
|
36
38
|
tex: string,
|
|
37
39
|
type: ASYMPTOTE,
|
|
38
40
|
zero: IZero,
|
|
41
|
+
tableOfSign: ITableOfSigns
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
export enum FUNCTION_EXTREMA {
|
|
@@ -69,9 +72,9 @@ export interface ITableOfSigns {
|
|
|
69
72
|
}
|
|
70
73
|
|
|
71
74
|
export enum TABLE_OF_SIGNS {
|
|
72
|
-
|
|
73
|
-
GROWS,
|
|
74
|
-
VARIATIONS
|
|
75
|
+
SIGNS = "signs",
|
|
76
|
+
GROWS = "grows",
|
|
77
|
+
VARIATIONS = "variatins"
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
/**
|
|
@@ -251,6 +254,9 @@ export class Study {
|
|
|
251
254
|
xTex: string, yTex: string,
|
|
252
255
|
pointType: FUNCTION_EXTREMA
|
|
253
256
|
|
|
257
|
+
// TODO: NumExp should parse something that isn't yet plotFunction
|
|
258
|
+
let exp = new NumExp(this.fx.plotFunction)
|
|
259
|
+
|
|
254
260
|
if (zero instanceof Fraction) {
|
|
255
261
|
let value: Fraction = zero,
|
|
256
262
|
evalY = this.fx.evaluate(value)
|
|
@@ -261,7 +267,7 @@ export class Study {
|
|
|
261
267
|
yTex = evalY.tex
|
|
262
268
|
} else {
|
|
263
269
|
x = zeroes[i].value
|
|
264
|
-
y =
|
|
270
|
+
y = exp.evaluate({x})
|
|
265
271
|
|
|
266
272
|
xTex = x.toFixed(2)
|
|
267
273
|
yTex = y.toFixed(2)
|
|
@@ -317,7 +323,7 @@ export class Study {
|
|
|
317
323
|
|
|
318
324
|
makeSigns(): ITableOfSigns {
|
|
319
325
|
return {
|
|
320
|
-
type: TABLE_OF_SIGNS.
|
|
326
|
+
type: TABLE_OF_SIGNS.SIGNS,
|
|
321
327
|
fx: null,
|
|
322
328
|
factors: [],
|
|
323
329
|
zeroes: [],
|
|
@@ -390,4 +396,41 @@ export class Study {
|
|
|
390
396
|
|
|
391
397
|
return tex
|
|
392
398
|
}
|
|
399
|
+
|
|
400
|
+
drawCode = (): string => {
|
|
401
|
+
// Function as string
|
|
402
|
+
let code = `f(x)=${this.fx.plotFunction}`
|
|
403
|
+
|
|
404
|
+
// Asymptotes
|
|
405
|
+
let i: number = 1
|
|
406
|
+
this.asymptotes.forEach(asymptote => {
|
|
407
|
+
if (asymptote.type === ASYMPTOTE.VERTICAL) {
|
|
408
|
+
code += `\nav_${i}=line x=${asymptote.zero.value}->red,dash`
|
|
409
|
+
i++
|
|
410
|
+
} else if (asymptote.type === ASYMPTOTE.HORIZONTAL) {
|
|
411
|
+
code += `\nah=line y=${asymptote.fx.monoms[0].coefficient.value}->orange,dash`
|
|
412
|
+
} else if (asymptote.type === ASYMPTOTE.SLOPE) {
|
|
413
|
+
code += `\nao=line y=${asymptote.fx.plotFunction}->red,dash`
|
|
414
|
+
}
|
|
415
|
+
i++
|
|
416
|
+
})
|
|
417
|
+
|
|
418
|
+
// Extremes
|
|
419
|
+
for (let zero in this.derivative.extremes) {
|
|
420
|
+
let extreme = this.derivative.extremes[zero]
|
|
421
|
+
|
|
422
|
+
code += `\nM_${i}(${extreme.value.x},${extreme.value.y})*`
|
|
423
|
+
i++
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// Zeroes
|
|
427
|
+
this.zeroes.forEach(zero => {
|
|
428
|
+
if (zero.type === ZEROTYPE.ZERO) {
|
|
429
|
+
code += `\nZ_${i}(${zero.value},0)*`
|
|
430
|
+
i++
|
|
431
|
+
}
|
|
432
|
+
})
|
|
433
|
+
|
|
434
|
+
return code
|
|
435
|
+
}
|
|
393
436
|
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import {Numeric} from "../numeric";
|
|
2
2
|
|
|
3
|
-
export type FractionParsingType = number|string|Fraction
|
|
3
|
+
export type FractionParsingType = number | string | Fraction
|
|
4
|
+
|
|
4
5
|
/**
|
|
5
6
|
* The fraction class make possible to handle
|
|
6
7
|
* TODO: Write the documentation correctly.
|
|
7
8
|
* \\(\frac{a}{b}\\) or \\[\frac{a}{b}\\] values.
|
|
8
9
|
*/
|
|
9
10
|
export class Fraction {
|
|
10
|
-
private _numerator: number;
|
|
11
11
|
private _denominator: number;
|
|
12
|
+
private _numerator: number;
|
|
12
13
|
|
|
13
14
|
constructor(value?: unknown, denominatorOrPeriodic?: number) {
|
|
14
15
|
this._numerator = 1;
|
|
@@ -47,24 +48,32 @@ export class Fraction {
|
|
|
47
48
|
|
|
48
49
|
// Display getter
|
|
49
50
|
get tex(): string {
|
|
50
|
-
if(this.isInfinity()){
|
|
51
|
-
return `${this.sign()===1?'+':'-'}\\infty`
|
|
51
|
+
if (this.isInfinity()) {
|
|
52
|
+
return `${this.sign() === 1 ? '+' : '-'}\\infty`
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
if (this.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
if (this.isExact()) {
|
|
56
|
+
if (this._denominator === 1) {
|
|
57
|
+
return `${this._numerator}`;
|
|
58
|
+
} else if (this._numerator < 0) {
|
|
59
|
+
return `-\\frac{ ${-this._numerator} }{ ${this._denominator} }`;
|
|
60
|
+
} else {
|
|
61
|
+
return `\\frac{ ${this._numerator} }{ ${this._denominator} }`;
|
|
62
|
+
}
|
|
58
63
|
} else {
|
|
59
|
-
return
|
|
64
|
+
return this.value.toFixed(3)
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
67
|
|
|
63
68
|
get display(): string {
|
|
64
|
-
if (this.
|
|
65
|
-
|
|
69
|
+
if (this.isExact()) {
|
|
70
|
+
if (this._denominator === 1) {
|
|
71
|
+
return `${this._numerator}`;
|
|
72
|
+
} else {
|
|
73
|
+
return `${this._numerator}/${this._denominator}`;
|
|
74
|
+
}
|
|
66
75
|
} else {
|
|
67
|
-
return
|
|
76
|
+
return this.value.toFixed(3)
|
|
68
77
|
}
|
|
69
78
|
}
|
|
70
79
|
|
|
@@ -76,12 +85,89 @@ export class Fraction {
|
|
|
76
85
|
get dfrac(): string {
|
|
77
86
|
return this.tex.replace('\\frac', '\\dfrac');
|
|
78
87
|
}
|
|
88
|
+
|
|
79
89
|
get tfrac(): string {
|
|
80
90
|
return this.tex.replace('\\frac', '\\tfrac')
|
|
81
91
|
}
|
|
82
92
|
|
|
93
|
+
static max = (...fractions: (Fraction | number)[]): Fraction => {
|
|
94
|
+
let M = new Fraction(fractions[0])
|
|
95
|
+
|
|
96
|
+
for (let m of fractions) {
|
|
97
|
+
let compare = new Fraction(m)
|
|
98
|
+
if (compare.greater(M)) {
|
|
99
|
+
M = compare.clone()
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return M
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static min = (...fractions: (Fraction | number)[]): Fraction => {
|
|
107
|
+
let M = new Fraction(fractions[0])
|
|
108
|
+
|
|
109
|
+
for (let m of fractions) {
|
|
110
|
+
let compare = new Fraction(m)
|
|
111
|
+
if (compare.lesser(M)) {
|
|
112
|
+
M = compare.clone()
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return M
|
|
117
|
+
}
|
|
118
|
+
|
|
83
119
|
// ------------------------------------------
|
|
84
120
|
// Creation / parsing functions
|
|
121
|
+
|
|
122
|
+
static average = (...fractions: (Fraction | number)[]): Fraction => {
|
|
123
|
+
let M = new Fraction().zero()
|
|
124
|
+
|
|
125
|
+
for (let f of fractions) {
|
|
126
|
+
M.add(f)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
M.divide(fractions.length)
|
|
130
|
+
|
|
131
|
+
return M
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
static unique = (fractions: Fraction[], sorted?: boolean): Fraction[] => {
|
|
135
|
+
// TODO: make sure it's wokring -> test !
|
|
136
|
+
let unique: { [Key: string]: boolean } = {},
|
|
137
|
+
distinct: Fraction[] = []
|
|
138
|
+
fractions.forEach(x => {
|
|
139
|
+
if (!unique[x.clone().reduce().tex]) {
|
|
140
|
+
distinct.push(x.clone())
|
|
141
|
+
unique[x.tex] = true
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
if (sorted) {
|
|
146
|
+
return Fraction.sort(distinct)
|
|
147
|
+
} else {
|
|
148
|
+
return distinct
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
static sort = (fractions: Fraction[], reverse?: boolean): Fraction[] => {
|
|
153
|
+
// Todo make sure it's the correct order, not reverse -> make a test
|
|
154
|
+
let sorted = fractions.sort((a, b) => a.value - b.value)
|
|
155
|
+
|
|
156
|
+
if (reverse) {
|
|
157
|
+
sorted.reverse()
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return sorted
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
isApproximative = (): boolean => {
|
|
164
|
+
return this._numerator.toString().length >= 15 && this._denominator.toString().length >= 15
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
isExact = (): boolean => {
|
|
168
|
+
return !this.isApproximative()
|
|
169
|
+
}
|
|
170
|
+
|
|
85
171
|
// ------------------------------------------
|
|
86
172
|
/**
|
|
87
173
|
* Parse the value to get the numerator and denominator
|
|
@@ -100,16 +186,15 @@ export class Fraction {
|
|
|
100
186
|
|
|
101
187
|
switch (typeof value) {
|
|
102
188
|
case "string":
|
|
103
|
-
// Split the
|
|
189
|
+
// Split the string value in two parts: Numerator/Denominator
|
|
104
190
|
S = value.split('/');
|
|
105
191
|
|
|
106
192
|
// Security checks
|
|
107
|
-
if (S.length > 2) throw "
|
|
108
|
-
if (S.map(x => x === '' || isNaN(Number(x))).includes(true)) throw "
|
|
109
|
-
|
|
193
|
+
if (S.length > 2) throw value + " has too many divide signs";
|
|
194
|
+
if (S.map(x => x === '' || isNaN(Number(x))).includes(true)) throw value + " is not a valid number"
|
|
110
195
|
|
|
111
196
|
if (S.length === 1) {
|
|
112
|
-
// No divide sign
|
|
197
|
+
// No divide sign - it's a number
|
|
113
198
|
return this.parse(+S[0]);
|
|
114
199
|
} else if (S.length === 2) {
|
|
115
200
|
// One divide signe
|
|
@@ -123,6 +208,7 @@ export class Fraction {
|
|
|
123
208
|
}
|
|
124
209
|
} else {
|
|
125
210
|
// More than one divide sign ?
|
|
211
|
+
// This is impossible
|
|
126
212
|
this._numerator = NaN;
|
|
127
213
|
this._denominator = 1;
|
|
128
214
|
}
|
|
@@ -164,6 +250,9 @@ export class Fraction {
|
|
|
164
250
|
return this;
|
|
165
251
|
};
|
|
166
252
|
|
|
253
|
+
// ------------------------------------------
|
|
254
|
+
// Mathematical operations
|
|
255
|
+
|
|
167
256
|
clone = (): Fraction => {
|
|
168
257
|
let F = new Fraction();
|
|
169
258
|
F.numerator = +this._numerator;
|
|
@@ -195,8 +284,6 @@ export class Fraction {
|
|
|
195
284
|
return this;
|
|
196
285
|
};
|
|
197
286
|
|
|
198
|
-
// ------------------------------------------
|
|
199
|
-
// Mathematical operations
|
|
200
287
|
// ------------------------------------------
|
|
201
288
|
opposed = (): Fraction => {
|
|
202
289
|
this._numerator = -this._numerator;
|
|
@@ -259,6 +346,7 @@ export class Fraction {
|
|
|
259
346
|
|
|
260
347
|
return this;
|
|
261
348
|
}
|
|
349
|
+
|
|
262
350
|
pow = (p: number | Fraction): Fraction => {
|
|
263
351
|
// TODO: Fraction.pow with a value different than a safe integer !
|
|
264
352
|
if (p instanceof Fraction) {
|
|
@@ -275,13 +363,13 @@ export class Fraction {
|
|
|
275
363
|
let controlNumerator = Math.floor(Math.pow(this._numerator, Math.abs(p))),
|
|
276
364
|
controlDenominator = Math.floor(Math.pow(this._denominator, Math.abs(p)))
|
|
277
365
|
|
|
278
|
-
if(controlNumerator ** Math.abs(p) === this._numerator
|
|
366
|
+
if (controlNumerator ** Math.abs(p) === this._numerator
|
|
279
367
|
&&
|
|
280
|
-
controlDenominator ** Math.abs(p) === this._denominator){
|
|
368
|
+
controlDenominator ** Math.abs(p) === this._denominator) {
|
|
281
369
|
|
|
282
370
|
this._numerator = this._numerator ** Math.abs(p);
|
|
283
371
|
this._denominator = this._denominator ** Math.abs(p);
|
|
284
|
-
}else{
|
|
372
|
+
} else {
|
|
285
373
|
this._numerator = this._numerator ** Math.abs(p);
|
|
286
374
|
this._denominator = this._denominator ** Math.abs(p);
|
|
287
375
|
}
|
|
@@ -320,72 +408,9 @@ export class Fraction {
|
|
|
320
408
|
return this;
|
|
321
409
|
};
|
|
322
410
|
|
|
323
|
-
|
|
324
|
-
static max = (...fractions: (Fraction | number)[]): Fraction => {
|
|
325
|
-
let M = new Fraction(fractions[0])
|
|
326
|
-
|
|
327
|
-
for (let m of fractions) {
|
|
328
|
-
let compare = new Fraction(m)
|
|
329
|
-
if (compare.greater(M)) {
|
|
330
|
-
M = compare.clone()
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
return M
|
|
335
|
-
}
|
|
336
|
-
static min = (...fractions: (Fraction | number)[]): Fraction => {
|
|
337
|
-
let M = new Fraction(fractions[0])
|
|
338
|
-
|
|
339
|
-
for (let m of fractions) {
|
|
340
|
-
let compare = new Fraction(m)
|
|
341
|
-
if (compare.lesser(M)) {
|
|
342
|
-
M = compare.clone()
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
return M
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
static average = (...fractions: (Fraction|number)[]): Fraction => {
|
|
350
|
-
let M = new Fraction().zero()
|
|
351
|
-
|
|
352
|
-
for(let f of fractions){
|
|
353
|
-
M.add(f)
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
M.divide(fractions.length)
|
|
357
|
-
|
|
358
|
-
return M
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
static unique = (fractions: Fraction[], sorted?: boolean): Fraction[] => {
|
|
362
|
-
// TODO: make sure it's wokring -> test !
|
|
363
|
-
let unique:{[Key:string]:boolean} = {},
|
|
364
|
-
distinct: Fraction[] = []
|
|
365
|
-
fractions.forEach(x => {
|
|
366
|
-
if(!unique[x.clone().reduce().tex]){
|
|
367
|
-
distinct.push(x.clone())
|
|
368
|
-
unique[x.tex]=true
|
|
369
|
-
}
|
|
370
|
-
})
|
|
371
|
-
|
|
372
|
-
if(sorted) {
|
|
373
|
-
return Fraction.sort(distinct)
|
|
374
|
-
}else{
|
|
375
|
-
return distinct
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
static sort = (fractions: Fraction[], reverse?:boolean): Fraction[] => {
|
|
379
|
-
// Todo make sure it's the correct order, not reverse -> make a test
|
|
380
|
-
let sorted = fractions.sort((a, b)=>a.value-b.value)
|
|
381
|
-
|
|
382
|
-
if(reverse){sorted.reverse()}
|
|
383
|
-
|
|
384
|
-
return sorted
|
|
385
|
-
}
|
|
386
|
-
|
|
387
411
|
// ------------------------------------------
|
|
388
412
|
// Mathematical operations specific to fractions
|
|
413
|
+
|
|
389
414
|
// ------------------------------------------
|
|
390
415
|
reduce = (): Fraction => {
|
|
391
416
|
let g = Numeric.gcd(this._numerator, this._denominator);
|