fable 3.1.64 → 3.1.65
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/docs/services/expression-parser-functions/README.md +9 -0
- package/docs/services/expression-parser-functions/beziercurvefit.md +57 -0
- package/docs/services/expression-parser-functions/bezierpoint.md +55 -0
- package/docs/services/expression-parser-functions/intercept.md +59 -0
- package/docs/services/expression-parser-functions/setvalue.md +55 -0
- package/docs/services/expression-parser-functions/slope.md +51 -0
- package/docs/services/expression-parser-functions/ternary.md +180 -0
- package/docs/services/expression-parser.md +72 -0
- package/example_applications/mathematical_playground/Math-Solver-Harness.js +108 -0
- package/example_applications/mathematical_playground/TestSuite-AcidTest.json +178 -0
- package/example_applications/mathematical_playground/TestSuite-Identities.json +147 -0
- package/example_applications/mathematical_playground/TestSuite-Precision.json +127 -0
- package/example_applications/mathematical_playground/TestSuite-Spreadsheet.json +198 -0
- package/package.json +1 -1
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer-DirectiveMutation.js +143 -0
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer.js +1 -1
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-FunctionMap.json +5 -4
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-TokenMap.json +65 -1
- package/source/services/Fable-Service-ExpressionParser.js +1 -0
- package/source/services/Fable-Service-Logic.js +33 -0
- package/source/services/Fable-Service-Math.js +78 -0
- package/test/ExpressionParser_tests.js +290 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Name": "Parser Acid Test",
|
|
3
|
+
"Description": "Stress tests for operator precedence, parenthesis handling, comparison operators, and ternary syntax. Catches common parser bugs.",
|
|
4
|
+
"Expressions":
|
|
5
|
+
[
|
|
6
|
+
{
|
|
7
|
+
"Category": "PEMDAS / Order of Operations",
|
|
8
|
+
"Description": "Multiplication before addition: 2 + 3*4 = 14",
|
|
9
|
+
"Equation": "Result = 2 + 3 * 4",
|
|
10
|
+
"ExpectedResult": "14"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"Category": "PEMDAS / Order of Operations",
|
|
14
|
+
"Description": "Parentheses override: (2+3)*4 = 20",
|
|
15
|
+
"Equation": "Result = (2 + 3) * 4",
|
|
16
|
+
"ExpectedResult": "20"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"Category": "PEMDAS / Order of Operations",
|
|
20
|
+
"Description": "Exponent before multiply: 2^3 * 4 = 32",
|
|
21
|
+
"Equation": "Result = 2^3 * 4",
|
|
22
|
+
"ExpectedResult": "32"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"Category": "PEMDAS / Order of Operations",
|
|
26
|
+
"Description": "Mixed all precedences: 2^3 + 4*5 - 6/3 = 26",
|
|
27
|
+
"Equation": "Result = 2^3 + 4 * 5 - 6 / 3",
|
|
28
|
+
"ExpectedResult": "26"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"Category": "PEMDAS / Order of Operations",
|
|
32
|
+
"Description": "Division before subtraction: 100 - 50 / 5 = 90",
|
|
33
|
+
"Equation": "Result = 100 - 50 / 5",
|
|
34
|
+
"ExpectedResult": "90"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"Category": "Parenthesis Nesting",
|
|
38
|
+
"Description": "Deep nesting: ((((1+2)*3)-4)/5) = 1",
|
|
39
|
+
"Equation": "Result = ((((1 + 2) * 3) - 4) / 5)",
|
|
40
|
+
"ExpectedResult": "1"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"Category": "Parenthesis Nesting",
|
|
44
|
+
"Description": "Redundant parentheses: ((((42)))) = 42",
|
|
45
|
+
"Equation": "Result = ((((42))))",
|
|
46
|
+
"ExpectedResult": "42"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"Category": "Left-to-Right Associativity",
|
|
50
|
+
"Description": "Subtraction is left-to-right: 10 - 3 - 2 = 5",
|
|
51
|
+
"Equation": "Result = 10 - 3 - 2",
|
|
52
|
+
"ExpectedResult": "5"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"Category": "Left-to-Right Associativity",
|
|
56
|
+
"Description": "Division is left-to-right: 20 / 4 / 5 = 1",
|
|
57
|
+
"Equation": "Result = 20 / 4 / 5",
|
|
58
|
+
"ExpectedResult": "1"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"Category": "Negative Numbers",
|
|
62
|
+
"Description": "(-3)^2 = 9 (parenthesized negative base)",
|
|
63
|
+
"Equation": "Result = (-3)^2",
|
|
64
|
+
"ExpectedResult": "9"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"Category": "Negative Numbers",
|
|
68
|
+
"Description": "Addition with negative: 4 + -3 = 1",
|
|
69
|
+
"Equation": "Result = 4 + -3",
|
|
70
|
+
"ExpectedResult": "1"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"Category": "Exponentiation",
|
|
74
|
+
"Description": "2^3^2 = 64 (left-to-right in this parser)",
|
|
75
|
+
"Equation": "Result = 2^3^2",
|
|
76
|
+
"ExpectedResult": "64"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"Category": "Comparison Operators",
|
|
80
|
+
"Description": "Greater than true: 5 > 3 = 1",
|
|
81
|
+
"Equation": "Result = 5 > 3",
|
|
82
|
+
"ExpectedResult": "1"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"Category": "Comparison Operators",
|
|
86
|
+
"Description": "Greater than false: 3 > 5 = 0",
|
|
87
|
+
"Equation": "Result = 3 > 5",
|
|
88
|
+
"ExpectedResult": "0"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"Category": "Comparison Operators",
|
|
92
|
+
"Description": "Equal true: 5 == 5 = 1",
|
|
93
|
+
"Equation": "Result = 5 == 5",
|
|
94
|
+
"ExpectedResult": "1"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"Category": "Comparison Operators",
|
|
98
|
+
"Description": "Not equal false: 5 != 5 = 0",
|
|
99
|
+
"Equation": "Result = 5 != 5",
|
|
100
|
+
"ExpectedResult": "0"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"Category": "Comparison Operators",
|
|
104
|
+
"Description": "GTE boundary: 3 >= 3 = 1",
|
|
105
|
+
"Equation": "Result = 3 >= 3",
|
|
106
|
+
"ExpectedResult": "1"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"Category": "Comparison Operators",
|
|
110
|
+
"Description": "LTE false: 3 <= 2 = 0",
|
|
111
|
+
"Equation": "Result = 3 <= 2",
|
|
112
|
+
"ExpectedResult": "0"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"Category": "Comparison Operators",
|
|
116
|
+
"Description": "Negative comparison: (-3) < 0 = 1",
|
|
117
|
+
"Equation": "Result = (-3) < 0",
|
|
118
|
+
"ExpectedResult": "1"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"Category": "Comparison Precedence",
|
|
122
|
+
"Description": "Arithmetic before comparison: 2+3 > 1+2 = 1",
|
|
123
|
+
"Equation": "Result = 2 + 3 > 1 + 2",
|
|
124
|
+
"ExpectedResult": "1"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"Category": "Ternary Operator",
|
|
128
|
+
"Description": "True branch: 5>3 ? 10+20 :: 30+40 = 30",
|
|
129
|
+
"Equation": "Result = 5 > 3 ? 10 + 20 :: 30 + 40",
|
|
130
|
+
"ExpectedResult": "30"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"Category": "Ternary Operator",
|
|
134
|
+
"Description": "False branch: 3>5 ? 10+20 :: 30+40 = 70",
|
|
135
|
+
"Equation": "Result = 3 > 5 ? 10 + 20 :: 30 + 40",
|
|
136
|
+
"ExpectedResult": "70"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"Category": "Ternary Operator",
|
|
140
|
+
"Description": "Nested ternary: 1>0 ? (2>3 ? 100 :: 200) :: 300 = 200",
|
|
141
|
+
"Equation": "Result = 1 > 0 ? (2 > 3 ? 100 :: 200) :: 300",
|
|
142
|
+
"ExpectedResult": "200"
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"Category": "Ternary Operator",
|
|
146
|
+
"Description": "Ternary with variables (absolute value pattern)",
|
|
147
|
+
"Equation": "Result = X > 0 ? X :: 0 - X",
|
|
148
|
+
"ExpectedResult": "5",
|
|
149
|
+
"Data": { "X": -5 }
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"Category": "Ternary Operator",
|
|
153
|
+
"Description": "Ternary with variables (positive input)",
|
|
154
|
+
"Equation": "Result = X > 0 ? X :: 0 - X",
|
|
155
|
+
"ExpectedResult": "5",
|
|
156
|
+
"Data": { "X": 5 }
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"Category": "Ternary Operator",
|
|
160
|
+
"Description": "Equality comparison in ternary",
|
|
161
|
+
"Equation": "Result = 0 == 0 ? 1 :: 0",
|
|
162
|
+
"ExpectedResult": "1"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"Category": "Functions with Comparisons",
|
|
166
|
+
"Description": "Function result in comparison via variable",
|
|
167
|
+
"Equation": "Result = SUM(Vals) > 5",
|
|
168
|
+
"ExpectedResult": "1",
|
|
169
|
+
"Data": { "Vals": [1, 2, 3] }
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"Category": "Complex Expressions",
|
|
173
|
+
"Description": "All arithmetic operators in one expression",
|
|
174
|
+
"Equation": "Result = (10 + 5) * 2 - 8 / 4 + 3^2 % 5",
|
|
175
|
+
"ExpectedResult": "37"
|
|
176
|
+
}
|
|
177
|
+
]
|
|
178
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Name": "Mathematical Identities",
|
|
3
|
+
"Description": "Classic mathematical identities from NIST DLMF and standard references. Tests correctness of trig, logarithmic, and algebraic operations.",
|
|
4
|
+
"Expressions":
|
|
5
|
+
[
|
|
6
|
+
{
|
|
7
|
+
"Category": "Pythagorean Identity",
|
|
8
|
+
"Description": "sin^2(30) + cos^2(30) = 1",
|
|
9
|
+
"Equation": "Result = ROUND(sin(rad(30))^2 + cos(rad(30))^2, 10)",
|
|
10
|
+
"ExpectedResult": "1"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"Category": "Pythagorean Identity",
|
|
14
|
+
"Description": "sin^2(45) + cos^2(45) = 1",
|
|
15
|
+
"Equation": "Result = ROUND(sin(rad(45))^2 + cos(rad(45))^2, 10)",
|
|
16
|
+
"ExpectedResult": "1"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"Category": "Pythagorean Identity",
|
|
20
|
+
"Description": "sin^2(60) + cos^2(60) = 1",
|
|
21
|
+
"Equation": "Result = ROUND(sin(rad(60))^2 + cos(rad(60))^2, 10)",
|
|
22
|
+
"ExpectedResult": "1"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"Category": "Double Angle Formula",
|
|
26
|
+
"Description": "2*sin(30)*cos(30) = sin(60)",
|
|
27
|
+
"Equation": "Result = ROUND(2 * sin(rad(30)) * cos(rad(30)), 10)",
|
|
28
|
+
"ExpectedResult": "0.8660254038"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"Category": "Double Angle Formula",
|
|
32
|
+
"Description": "sin(60) directly for comparison",
|
|
33
|
+
"Equation": "Result = ROUND(sin(rad(60)), 10)",
|
|
34
|
+
"ExpectedResult": "0.8660254038"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"Category": "Tangent Identity",
|
|
38
|
+
"Description": "tan(45) = 1",
|
|
39
|
+
"Equation": "Result = ROUND(tan(rad(45)), 10)",
|
|
40
|
+
"ExpectedResult": "1"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"Category": "Power and Root",
|
|
44
|
+
"Description": "sqrt(x)^2 = x (within rounding)",
|
|
45
|
+
"Equation": "Result = ROUND(sqrt(7)^2, 10)",
|
|
46
|
+
"ExpectedResult": "7"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"Category": "Power and Root",
|
|
50
|
+
"Description": "sqrt(144) = 12 (perfect square)",
|
|
51
|
+
"Equation": "Result = sqrt(144)",
|
|
52
|
+
"ExpectedResult": "12"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"Category": "Power and Root",
|
|
56
|
+
"Description": "x^0 = 1 for any nonzero x",
|
|
57
|
+
"Equation": "Result = 5^0",
|
|
58
|
+
"ExpectedResult": "1"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"Category": "Power and Root",
|
|
62
|
+
"Description": "x^1 = x",
|
|
63
|
+
"Equation": "Result = 7^1",
|
|
64
|
+
"ExpectedResult": "7"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"Category": "Power and Root",
|
|
68
|
+
"Description": "x^2 * x^3 = x^5 (exponent addition)",
|
|
69
|
+
"Equation": "Result = 2^2 * 2^3",
|
|
70
|
+
"ExpectedResult": "32"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"Category": "Algebraic Identity",
|
|
74
|
+
"Description": "(a+b)(a-b) = a^2 - b^2 (difference of squares)",
|
|
75
|
+
"Equation": "Result = (A + B) * (A - B)",
|
|
76
|
+
"ExpectedResult": "40",
|
|
77
|
+
"Data": { "A": 7, "B": 3 }
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"Category": "Algebraic Identity",
|
|
81
|
+
"Description": "a^2 - b^2 directly for comparison",
|
|
82
|
+
"Equation": "Result = A^2 - B^2",
|
|
83
|
+
"ExpectedResult": "40",
|
|
84
|
+
"Data": { "A": 7, "B": 3 }
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"Category": "Algebraic Identity",
|
|
88
|
+
"Description": "(a+b)^2 = a^2 + 2ab + b^2",
|
|
89
|
+
"Equation": "Result = (3 + 4)^2",
|
|
90
|
+
"ExpectedResult": "49"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"Category": "Algebraic Identity",
|
|
94
|
+
"Description": "a^2 + 2ab + b^2 directly for comparison",
|
|
95
|
+
"Equation": "Result = 3^2 + 2 * 3 * 4 + 4^2",
|
|
96
|
+
"ExpectedResult": "49"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"Category": "Reciprocal Identity",
|
|
100
|
+
"Description": "1/(1/x) = x (within rounding)",
|
|
101
|
+
"Equation": "Result = ROUND(1 / (1 / 7), 10)",
|
|
102
|
+
"ExpectedResult": "7"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"Category": "Constants",
|
|
106
|
+
"Description": "Pi starts with 3.14159265",
|
|
107
|
+
"Equation": "Result = ROUND(pi(), 8)",
|
|
108
|
+
"ExpectedResult": "3.14159265"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"Category": "Constants",
|
|
112
|
+
"Description": "Euler's number starts with 2.71828183",
|
|
113
|
+
"Equation": "Result = ROUND(euler(), 8)",
|
|
114
|
+
"ExpectedResult": "2.71828183"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"Category": "Logarithmic Identity",
|
|
118
|
+
"Description": "log(1) = 0",
|
|
119
|
+
"Equation": "Result = log(1)",
|
|
120
|
+
"ExpectedResult": "0.000000000"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"Category": "Logarithmic Identity",
|
|
124
|
+
"Description": "exp(0) = 1",
|
|
125
|
+
"Equation": "Result = exp(0)",
|
|
126
|
+
"ExpectedResult": "1"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"Category": "Additive Identity",
|
|
130
|
+
"Description": "x + 0 = x",
|
|
131
|
+
"Equation": "Result = 42 + 0",
|
|
132
|
+
"ExpectedResult": "42"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"Category": "Multiplicative Identity",
|
|
136
|
+
"Description": "x * 1 = x",
|
|
137
|
+
"Equation": "Result = 42 * 1",
|
|
138
|
+
"ExpectedResult": "42"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"Category": "Multiplicative Zero",
|
|
142
|
+
"Description": "x * 0 = 0",
|
|
143
|
+
"Equation": "Result = 42 * 0",
|
|
144
|
+
"ExpectedResult": "0"
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Name": "Numeric Precision Stress Tests",
|
|
3
|
+
"Description": "Tests that catch IEEE 754 floating-point errors. The expression parser uses big.js for arbitrary precision, so these should all pass cleanly.",
|
|
4
|
+
"Expressions":
|
|
5
|
+
[
|
|
6
|
+
{
|
|
7
|
+
"Category": "IEEE 754 Traps",
|
|
8
|
+
"Description": "0.1 + 0.2 = 0.3 (classic IEEE 754 failure)",
|
|
9
|
+
"Equation": "Result = 0.1 + 0.2",
|
|
10
|
+
"ExpectedResult": "0.3"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"Category": "IEEE 754 Traps",
|
|
14
|
+
"Description": "0.3 - 0.1 = 0.2",
|
|
15
|
+
"Equation": "Result = 0.3 - 0.1",
|
|
16
|
+
"ExpectedResult": "0.2"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"Category": "IEEE 754 Traps",
|
|
20
|
+
"Description": "0.7 + 0.1 = 0.8",
|
|
21
|
+
"Equation": "Result = 0.7 + 0.1",
|
|
22
|
+
"ExpectedResult": "0.8"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"Category": "IEEE 754 Traps",
|
|
26
|
+
"Description": "-0.1 + -0.2 = -0.3",
|
|
27
|
+
"Equation": "Result = -0.1 + -0.2",
|
|
28
|
+
"ExpectedResult": "-0.3"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"Category": "IEEE 754 Traps",
|
|
32
|
+
"Description": "1.0 - 0.9 - 0.1 = 0 (catastrophic cancellation)",
|
|
33
|
+
"Equation": "Result = 1.0 - 0.9 - 0.1",
|
|
34
|
+
"ExpectedResult": "0"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"Category": "Large Numbers",
|
|
38
|
+
"Description": "Large integer multiplication",
|
|
39
|
+
"Equation": "Result = 99999999999999 * 99999999999999",
|
|
40
|
+
"ExpectedResult": "9.999999999999800000000000001e+27"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"Category": "Large Numbers",
|
|
44
|
+
"Description": "Large integer addition",
|
|
45
|
+
"Equation": "Result = 123456789012345 + 987654321098765",
|
|
46
|
+
"ExpectedResult": "1111111110111110"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"Category": "Large Numbers",
|
|
50
|
+
"Description": "2^53 exact (JavaScript MAX_SAFE_INTEGER + 1)",
|
|
51
|
+
"Equation": "Result = 2^53",
|
|
52
|
+
"ExpectedResult": "9007199254740992"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"Category": "Small Number Precision",
|
|
56
|
+
"Description": "Subtraction preserving small difference",
|
|
57
|
+
"Equation": "Result = 1000000.001 - 1000000",
|
|
58
|
+
"ExpectedResult": "0.001"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"Category": "Small Number Precision",
|
|
62
|
+
"Description": "Very small number multiplication",
|
|
63
|
+
"Equation": "Result = 0.000001 * 0.000001",
|
|
64
|
+
"ExpectedResult": "1e-12"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"Category": "Division Precision",
|
|
68
|
+
"Description": "1/3 * 3 approaches 1 (repeating decimal)",
|
|
69
|
+
"Equation": "Result = ROUND(1 / 3 * 3, 10)",
|
|
70
|
+
"ExpectedResult": "1"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"Category": "Division Precision",
|
|
74
|
+
"Description": "Large number / same number = 1 (within rounding)",
|
|
75
|
+
"Equation": "Result = ROUND(1000000 / 7 * 7, 10)",
|
|
76
|
+
"ExpectedResult": "1000000"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"Category": "Division Precision",
|
|
80
|
+
"Description": "1 / 1000000 = 0.000001",
|
|
81
|
+
"Equation": "Result = 1 / 1000000",
|
|
82
|
+
"ExpectedResult": "0.000001"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"Category": "Chained Operations",
|
|
86
|
+
"Description": "Add then subtract should cancel exactly",
|
|
87
|
+
"Equation": "Result = ((((1 + 0.0001) - 0.0001) * 10000) / 10000)",
|
|
88
|
+
"ExpectedResult": "1"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"Category": "Modulus",
|
|
92
|
+
"Description": "10 % 3 = 1",
|
|
93
|
+
"Equation": "Result = 10 % 3",
|
|
94
|
+
"ExpectedResult": "1"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"Category": "Modulus",
|
|
98
|
+
"Description": "7.5 % 2.5 = 0 (exact division)",
|
|
99
|
+
"Equation": "Result = 7.5 % 2.5",
|
|
100
|
+
"ExpectedResult": "0"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"Category": "Power Precision",
|
|
104
|
+
"Description": "3^7 = 2187",
|
|
105
|
+
"Equation": "Result = 3^7",
|
|
106
|
+
"ExpectedResult": "2187"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"Category": "Power Precision",
|
|
110
|
+
"Description": "10^10 = 10000000000",
|
|
111
|
+
"Equation": "Result = 10^10",
|
|
112
|
+
"ExpectedResult": "10000000000"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"Category": "Negative Number Precision",
|
|
116
|
+
"Description": "(-1)^2 = 1",
|
|
117
|
+
"Equation": "Result = (-1)^2",
|
|
118
|
+
"ExpectedResult": "1"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"Category": "Negative Number Precision",
|
|
122
|
+
"Description": "(-2) * (-3) = 6",
|
|
123
|
+
"Equation": "Result = (-2) * (-3)",
|
|
124
|
+
"ExpectedResult": "6"
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Name": "Spreadsheet Function Conformance",
|
|
3
|
+
"Description": "Excel/OpenFormula-compatible function tests. Verifies statistical, rounding, and regression functions against known reference values.",
|
|
4
|
+
"Expressions":
|
|
5
|
+
[
|
|
6
|
+
{
|
|
7
|
+
"Category": "Aggregation",
|
|
8
|
+
"Description": "SUM of five values",
|
|
9
|
+
"Equation": "Result = SUM(Vals)",
|
|
10
|
+
"ExpectedResult": "150",
|
|
11
|
+
"Data": { "Vals": [10, 20, 30, 40, 50] }
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"Category": "Aggregation",
|
|
15
|
+
"Description": "AVG of five values",
|
|
16
|
+
"Equation": "Result = AVG(Vals)",
|
|
17
|
+
"ExpectedResult": "30",
|
|
18
|
+
"Data": { "Vals": [10, 20, 30, 40, 50] }
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"Category": "Aggregation",
|
|
22
|
+
"Description": "MEAN is equivalent to AVG",
|
|
23
|
+
"Equation": "Result = MEAN(Vals)",
|
|
24
|
+
"ExpectedResult": "30",
|
|
25
|
+
"Data": { "Vals": [10, 20, 30, 40, 50] }
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"Category": "Aggregation",
|
|
29
|
+
"Description": "MEDIAN of odd-count dataset",
|
|
30
|
+
"Equation": "Result = MEDIAN(Vals)",
|
|
31
|
+
"ExpectedResult": "30",
|
|
32
|
+
"Data": { "Vals": [10, 20, 30, 40, 50] }
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"Category": "Aggregation",
|
|
36
|
+
"Description": "MEDIAN of even-count dataset (average of middle two)",
|
|
37
|
+
"Equation": "Result = MEDIAN(Vals)",
|
|
38
|
+
"ExpectedResult": "25",
|
|
39
|
+
"Data": { "Vals": [10, 20, 30, 40] }
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"Category": "Aggregation",
|
|
43
|
+
"Description": "MEDIAN of single element",
|
|
44
|
+
"Equation": "Result = MEDIAN(Vals)",
|
|
45
|
+
"ExpectedResult": "42",
|
|
46
|
+
"Data": { "Vals": [42] }
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"Category": "Aggregation",
|
|
50
|
+
"Description": "MIN of dataset",
|
|
51
|
+
"Equation": "Result = MIN(Vals)",
|
|
52
|
+
"ExpectedResult": "10",
|
|
53
|
+
"Data": { "Vals": [10, 20, 30, 40, 50] }
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"Category": "Aggregation",
|
|
57
|
+
"Description": "MAX of dataset",
|
|
58
|
+
"Equation": "Result = MAX(Vals)",
|
|
59
|
+
"ExpectedResult": "50",
|
|
60
|
+
"Data": { "Vals": [10, 20, 30, 40, 50] }
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"Category": "Aggregation",
|
|
64
|
+
"Description": "MAX of identical values",
|
|
65
|
+
"Equation": "Result = MAX(Vals)",
|
|
66
|
+
"ExpectedResult": "5",
|
|
67
|
+
"Data": { "Vals": [5, 5, 5] }
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"Category": "Aggregation",
|
|
71
|
+
"Description": "MIN of single element",
|
|
72
|
+
"Equation": "Result = MIN(Vals)",
|
|
73
|
+
"ExpectedResult": "42",
|
|
74
|
+
"Data": { "Vals": [42] }
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"Category": "Aggregation",
|
|
78
|
+
"Description": "COUNT of dataset",
|
|
79
|
+
"Equation": "Result = COUNT(Vals)",
|
|
80
|
+
"ExpectedResult": "5",
|
|
81
|
+
"Data": { "Vals": [10, 20, 30, 40, 50] }
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"Category": "Variance and Standard Deviation",
|
|
85
|
+
"Description": "Sample variance (VAR) — Excel reference: 2,4,4,4,5,5,7,9 = 4.571429",
|
|
86
|
+
"Equation": "Result = ROUND(VAR(Vals), 4)",
|
|
87
|
+
"ExpectedResult": "4.5714",
|
|
88
|
+
"Data": { "Vals": [2, 4, 4, 4, 5, 5, 7, 9] }
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"Category": "Variance and Standard Deviation",
|
|
92
|
+
"Description": "Population variance (VARP) — Excel reference: 2,4,4,4,5,5,7,9 = 4",
|
|
93
|
+
"Equation": "Result = VARP(Vals)",
|
|
94
|
+
"ExpectedResult": "4",
|
|
95
|
+
"Data": { "Vals": [2, 4, 4, 4, 5, 5, 7, 9] }
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"Category": "Variance and Standard Deviation",
|
|
99
|
+
"Description": "Sample standard deviation (STDEV) — Excel reference: 2.138090",
|
|
100
|
+
"Equation": "Result = ROUND(STDEV(Vals), 4)",
|
|
101
|
+
"ExpectedResult": "2.1381",
|
|
102
|
+
"Data": { "Vals": [2, 4, 4, 4, 5, 5, 7, 9] }
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"Category": "Variance and Standard Deviation",
|
|
106
|
+
"Description": "Population standard deviation (STDEVP) — Excel reference: 2",
|
|
107
|
+
"Equation": "Result = STDEVP(Vals)",
|
|
108
|
+
"ExpectedResult": "2",
|
|
109
|
+
"Data": { "Vals": [2, 4, 4, 4, 5, 5, 7, 9] }
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"Category": "Rounding",
|
|
113
|
+
"Description": "ROUND to nearest integer",
|
|
114
|
+
"Equation": "Result = ROUND(3.14159)",
|
|
115
|
+
"ExpectedResult": "3"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"Category": "Rounding",
|
|
119
|
+
"Description": "ROUND half-up: 2.5 rounds to 3",
|
|
120
|
+
"Equation": "Result = ROUND(2.5)",
|
|
121
|
+
"ExpectedResult": "3"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"Category": "Rounding",
|
|
125
|
+
"Description": "ROUND to 1 decimal place",
|
|
126
|
+
"Equation": "Result = ROUND(2.55, 1)",
|
|
127
|
+
"ExpectedResult": "2.6"
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"Category": "Rounding",
|
|
131
|
+
"Description": "ROUND to 2 decimal places",
|
|
132
|
+
"Equation": "Result = ROUND(3.14159, 2)",
|
|
133
|
+
"ExpectedResult": "3.14"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"Category": "Rounding",
|
|
137
|
+
"Description": "ROUND to 4 decimal places",
|
|
138
|
+
"Equation": "Result = ROUND(3.14159, 4)",
|
|
139
|
+
"ExpectedResult": "3.1416"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"Category": "Rounding",
|
|
143
|
+
"Description": "TOFIXED pads with zeros",
|
|
144
|
+
"Equation": "Result = TOFIXED(3.1, 4)",
|
|
145
|
+
"ExpectedResult": "3.1000"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"Category": "Rounding",
|
|
149
|
+
"Description": "ABS of negative number",
|
|
150
|
+
"Equation": "Result = ABS(-5)",
|
|
151
|
+
"ExpectedResult": "5"
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"Category": "Rounding",
|
|
155
|
+
"Description": "ABS of positive number (identity)",
|
|
156
|
+
"Equation": "Result = ABS(5)",
|
|
157
|
+
"ExpectedResult": "5"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"Category": "Rounding",
|
|
161
|
+
"Description": "FLOOR rounds down",
|
|
162
|
+
"Equation": "Result = FLOOR(3.7)",
|
|
163
|
+
"ExpectedResult": "3"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"Category": "Rounding",
|
|
167
|
+
"Description": "FLOOR of negative rounds toward negative infinity",
|
|
168
|
+
"Equation": "Result = FLOOR(-3.2)",
|
|
169
|
+
"ExpectedResult": "-4"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"Category": "Rounding",
|
|
173
|
+
"Description": "CEIL rounds up",
|
|
174
|
+
"Equation": "Result = CEIL(3.2)",
|
|
175
|
+
"ExpectedResult": "4"
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"Category": "Rounding",
|
|
179
|
+
"Description": "CEIL of negative rounds toward zero",
|
|
180
|
+
"Equation": "Result = CEIL(-3.7)",
|
|
181
|
+
"ExpectedResult": "-3"
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"Category": "Linear Regression",
|
|
185
|
+
"Description": "SLOPE of perfect linear data y=2x (slope=2)",
|
|
186
|
+
"Equation": "Result = SLOPE(Y, X)",
|
|
187
|
+
"ExpectedResult": "2",
|
|
188
|
+
"Data": { "Y": [2, 4, 6, 8, 10], "X": [1, 2, 3, 4, 5] }
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
"Category": "Linear Regression",
|
|
192
|
+
"Description": "INTERCEPT of perfect linear data y=2x (intercept=0)",
|
|
193
|
+
"Equation": "Result = INTERCEPT(Y, X)",
|
|
194
|
+
"ExpectedResult": "0",
|
|
195
|
+
"Data": { "Y": [2, 4, 6, 8, 10], "X": [1, 2, 3, 4, 5] }
|
|
196
|
+
}
|
|
197
|
+
]
|
|
198
|
+
}
|