Skip to content

Commit b914cd3

Browse files
committed
Making it a npm package.
1 parent 650d21e commit b914cd3

File tree

3 files changed

+170
-169
lines changed

3 files changed

+170
-169
lines changed

.DS_Store

6 KB
Binary file not shown.

bisection.ts

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// Calculus Bisection Class Project
2+
// Author: Nicholas Assaderaghi (FlyN Nick)
3+
// Why did I write this in TypeScript: I felt like it :)
4+
5+
/** Returns the value of an expressios given x. */
6+
function convert(f: ((x: number) => number) | string, x: number): number
7+
{
8+
if (typeof f == 'string') { return eval(f); }
9+
else { return f(x); }
10+
}
11+
12+
/**
13+
* Bisection function.
14+
* Finds the root of a function within given range.
15+
*
16+
* Things that may cause this to be unsuccessfull/error:
17+
* #1: Root is not within given range.
18+
* #2: Function changes signs more than once within given range.
19+
* #3: The given minimum is greater than the given maximum.
20+
* #4: There are x within given range where f(x) is undefined.
21+
*
22+
* @param {(x: number) => any} f - function you want to find the root of.
23+
* @param {number} min - min of given range.
24+
* @param {number} max - max of given range.
25+
* @param {bool} annoyingConsoleLogs - (optional) really annoying console log ever iteration.
26+
* @param {number} maxIter - (optional) max number of iterations
27+
*/
28+
export function bisection(f: ((x: number) => number) | string, min: number, max: number, maxIter=100, annoyingConsoleLogs=false): number | [number, number] | 'ERROR'
29+
{
30+
console.log("---------------------------------------------------------------");
31+
32+
if (min > max)
33+
{
34+
console.log("You seem to have mixed the min and max...");
35+
return 'ERROR';
36+
}
37+
else if (min == max && convert(f, min) == 0)
38+
{
39+
console.log("Wow, the given min and max were the same and were the root. Kinda seems like this was on purpose...");
40+
return min;
41+
}
42+
else if (min == max)
43+
{
44+
console.log("Wow, the given min and max were the same but were not the root. Kinda seems like this was on purpose...");
45+
return 'ERROR';
46+
}
47+
else if (convert(f, min) == 0)
48+
{
49+
console.log("Wow, the lower bound of the given range was the root. Kinda seems like this was on purpose...");
50+
return min;
51+
}
52+
else if (convert(f, max) == 0)
53+
{
54+
console.log("Wow, the upper bound of the given range was the root. Kinda seems like this was on purpose...");
55+
return max;
56+
}
57+
58+
let posSlope = true;
59+
if (convert(f, min) > convert(f, (min+max/2))) { posSlope = false; }
60+
61+
let iter = 0;
62+
while (iter != maxIter)
63+
{
64+
iter++;
65+
let guess = (min+max)/2;
66+
67+
if ((convert(f, guess) < 0 && posSlope) || (convert(f, guess) > 0 && !posSlope))
68+
{
69+
if (guess == min)
70+
{
71+
console.log(`Stopped at iteration #${iter}.`);
72+
console.log(`Root not found.\nRange: (${min}, ${max}).`);
73+
return [min, max];
74+
}
75+
min = guess;
76+
}
77+
else if ((convert(f, guess) > 0 && posSlope) || (convert(f, guess) < 0 && !posSlope))
78+
{
79+
if (guess == max)
80+
{
81+
console.log(`Stopped at iteration #${iter}.`);
82+
console.log(`Root not found.\nRange: (${min}, ${max}).`);
83+
return [min, max];
84+
}
85+
max = guess;
86+
}
87+
else
88+
{
89+
console.log(`Root: ${guess}.\nIterations it took: ${iter}.`);
90+
return guess;
91+
}
92+
if (annoyingConsoleLogs)
93+
{
94+
console.log(`Iteration #${iter}:\n\tCurrent range: (${min}, ${max})`);
95+
}
96+
}
97+
98+
console.log(`Root not found (maximum iterations reached).\nRange: (${min}, ${max}).`);
99+
100+
console.log(`Remember, this algorithm will only work if:\n\t#1: The root is within the range.\n\t#2: The function changes sign once within the interval.`);
101+
102+
return [min, max];
103+
}
104+
105+
/**
106+
* Just testing if everything generally works.
107+
* This is not an in-depth test (does not test all error scenarios).
108+
*/
109+
export function testBisectionFunction()
110+
{
111+
console.log(`TESTING BISECTION FUNCTION!\n`);
112+
113+
/** Test linear function: (2x -19). */
114+
const linFunc = (x: number) => { return 2*x-19; }
115+
116+
/** Test linear function in string format. */
117+
const linFuncString = '2*x-19';
118+
119+
/** Test polynomial function: (x^2 + x - 5). */
120+
const polyFunc = (x: number) => { return x**2+x-5; }
121+
122+
/** First test trigonometric function: sin(1/x). */
123+
const trigFuncOne = (x: number) => { return Math.sin(1/x); }
124+
125+
/** Second test trigonometric function: sin(x)/x. */
126+
const trigFuncTwo = (x: number) => { return Math.sin(x)/x; }
127+
128+
const returnedVals: (number | [number, number] | 'ERROR')[] =
129+
[
130+
bisection(linFunc, 9.5, 9.5), // root is both given min and max
131+
bisection(linFunc, 5, 5), // given min and max are the same, but not the root
132+
bisection(linFunc, 9.5, 10), // root is the given min
133+
bisection(linFunc, 9, 9.5), // root is the given max
134+
bisection(linFunc, -100, 0), // root not within range
135+
bisection(linFunc, 100, -100), // upper and lower switched
136+
bisection(linFuncString, -100, 100),
137+
bisection(polyFunc, 0, 21),
138+
bisection(trigFuncOne, 0.212, 0.637, 100000),
139+
bisection(trigFuncTwo, 0.1, 4.25, 1000/*, true*/) // those console logs really are annoying...
140+
]
141+
142+
console.log("---------------------------------------------------------------");
143+
console.log(`\nReturned values from bisection function:\n[`);
144+
145+
// should I have just used a regular for loop: yes.
146+
let len = returnedVals.length;
147+
let i = 0;
148+
for (const returnedVal of returnedVals)
149+
{
150+
i++;
151+
let toPrint;
152+
switch (typeof returnedVal)
153+
{
154+
case 'string':
155+
toPrint = `\t${returnedVal}`;
156+
break;
157+
case 'number':
158+
toPrint = `\t${returnedVal}`;
159+
break;
160+
default:
161+
toPrint = `\t[${returnedVal[0]}, ${returnedVal[1]}]`;
162+
}
163+
if (i != len) { toPrint += ','; }
164+
else { toPrint += `\n]`; }
165+
console.log(toPrint);
166+
}
167+
}
168+
169+
//testBisectionFunction();

index.ts

Lines changed: 1 addition & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -1,169 +1 @@
1-
// Calculus Bisection Class Project
2-
// Author: Nicholas Assaderaghi (FlyN Nick)
3-
// Why did I write this in TypeScript: I felt like it :)
4-
5-
/** Returns the value of an expressios given x. */
6-
function convert(f: ((x: number) => number) | string, x: number): number
7-
{
8-
if (typeof f == 'string') { return eval(f); }
9-
else { return f(x); }
10-
}
11-
12-
/**
13-
* Bisection function.
14-
* Finds the root of a function within given range.
15-
*
16-
* Things that may cause this to be unsuccessfull/error:
17-
* #1: Root is not within given range.
18-
* #2: Function changes signs more than once within given range.
19-
* #3: The given minimum is greater than the given maximum.
20-
* #4: There are x within given range where f(x) is undefined.
21-
*
22-
* @param {(x: number) => any} f - function you want to find the root of.
23-
* @param {number} min - min of given range.
24-
* @param {number} max - max of given range.
25-
* @param {bool} annoyingConsoleLogs - (optional) really annoying console log ever iteration.
26-
* @param {number} maxIter - (optional) max number of iterations
27-
*/
28-
function bisection(f: ((x: number) => number) | string, min: number, max: number, maxIter=100, annoyingConsoleLogs=false): number | [number, number] | 'ERROR'
29-
{
30-
console.log("---------------------------------------------------------------");
31-
32-
if (min > max)
33-
{
34-
console.log("You seem to have mixed the min and max...");
35-
return 'ERROR';
36-
}
37-
else if (min == max && convert(f, min) == 0)
38-
{
39-
console.log("Wow, the given min and max were the same and were the root. Kinda seems like this was on purpose...");
40-
return min;
41-
}
42-
else if (min == max)
43-
{
44-
console.log("Wow, the given min and max were the same but were not the root. Kinda seems like this was on purpose...");
45-
return 'ERROR';
46-
}
47-
else if (convert(f, min) == 0)
48-
{
49-
console.log("Wow, the lower bound of the given range was the root. Kinda seems like this was on purpose...");
50-
return min;
51-
}
52-
else if (convert(f, max) == 0)
53-
{
54-
console.log("Wow, the upper bound of the given range was the root. Kinda seems like this was on purpose...");
55-
return max;
56-
}
57-
58-
let posSlope = true;
59-
if (convert(f, min) > convert(f, (min+max/2))) { posSlope = false; }
60-
61-
let iter = 0;
62-
while (iter != maxIter)
63-
{
64-
iter++;
65-
let guess = (min+max)/2;
66-
67-
if ((convert(f, guess) < 0 && posSlope) || (convert(f, guess) > 0 && !posSlope))
68-
{
69-
if (guess == min)
70-
{
71-
console.log(`Stopped at iteration #${iter}.`);
72-
console.log(`Root not found.\nRange: (${min}, ${max}).`);
73-
return [min, max];
74-
}
75-
min = guess;
76-
}
77-
else if ((convert(f, guess) > 0 && posSlope) || (convert(f, guess) < 0 && !posSlope))
78-
{
79-
if (guess == max)
80-
{
81-
console.log(`Stopped at iteration #${iter}.`);
82-
console.log(`Root not found.\nRange: (${min}, ${max}).`);
83-
return [min, max];
84-
}
85-
max = guess;
86-
}
87-
else
88-
{
89-
console.log(`Root: ${guess}.\nIterations it took: ${iter}.`);
90-
return guess;
91-
}
92-
if (annoyingConsoleLogs)
93-
{
94-
console.log(`Iteration #${iter}:\n\tCurrent range: (${min}, ${max})`);
95-
}
96-
}
97-
98-
console.log(`Root not found (maximum iterations reached).\nRange: (${min}, ${max}).`);
99-
100-
console.log(`Remember, this algorithm will only work if:\n\t#1: The root is within the range.\n\t#2: The function changes sign once within the interval.`);
101-
102-
return [min, max];
103-
}
104-
105-
/**
106-
* Just testing if everything generally works.
107-
* This is not an in-depth test (does not test all error scenarios).
108-
*/
109-
function testBisectionFunction()
110-
{
111-
console.log(`TESTING BISECTION FUNCTION!\n`);
112-
113-
/** Test linear function: (2x -19). */
114-
const linFunc = (x: number) => { return 2*x-19; }
115-
116-
/** Test linear function in string format. */
117-
const linFuncString = '2*x-19';
118-
119-
/** Test polynomial function: (x^2 + x - 5). */
120-
const polyFunc = (x: number) => { return x**2+x-5; }
121-
122-
/** First test trigonometric function: sin(1/x). */
123-
const trigFuncOne = (x: number) => { return Math.sin(1/x); }
124-
125-
/** Second test trigonometric function: sin(x)/x. */
126-
const trigFuncTwo = (x: number) => { return Math.sin(x)/x; }
127-
128-
const returnedVals: (number | [number, number] | 'ERROR')[] =
129-
[
130-
bisection(linFunc, 9.5, 9.5), // root is both given min and max
131-
bisection(linFunc, 5, 5), // given min and max are the same, but not the root
132-
bisection(linFunc, 9.5, 10), // root is the given min
133-
bisection(linFunc, 9, 9.5), // root is the given max
134-
bisection(linFunc, -100, 0), // root not within range
135-
bisection(linFunc, 100, -100), // upper and lower switched
136-
bisection(linFuncString, -100, 100),
137-
bisection(polyFunc, 0, 21),
138-
bisection(trigFuncOne, 0.212, 0.637, 100000),
139-
bisection(trigFuncTwo, 0.1, 4.25, 1000/*, true*/) // those console logs really are annoying...
140-
]
141-
142-
console.log("---------------------------------------------------------------");
143-
console.log(`\nReturned values from bisection function:\n[`);
144-
145-
// should I have just used a regular for loop: yes.
146-
let len = returnedVals.length;
147-
let i = 0;
148-
for (const returnedVal of returnedVals)
149-
{
150-
i++;
151-
let toPrint;
152-
switch (typeof returnedVal)
153-
{
154-
case 'string':
155-
toPrint = `\t${returnedVal}`;
156-
break;
157-
case 'number':
158-
toPrint = `\t${returnedVal}`;
159-
break;
160-
default:
161-
toPrint = `\t[${returnedVal[0]}, ${returnedVal[1]}]`;
162-
}
163-
if (i != len) { toPrint += ','; }
164-
else { toPrint += `\n]`; }
165-
console.log(toPrint);
166-
}
167-
}
168-
169-
testBisectionFunction();
1+
export { bisection, testBisectionFunction } from './bisection';

0 commit comments

Comments
 (0)