Tested prompt · Coding
Evaluate an arithmetic expression, no eval: every AI model's reply, tested
We sent this hard coding prompt to all 16 models in llmwise, the same way the app sends a message, and checked every reply the same way. Here's each one as it came, with whether it passed, what it cost and how long it took.
Based on 16 of our test runs on , through OpenRouter with the app's own prompt and settings. Updated .
Short answer
15 of 16 models passed this coding prompt's check (tests); Claude Haiku 4.5 didn't. The cheapest reply that passed was GLM 5.3 Flash's, at $0.00035; the fastest, Claude Sonnet 5.5's in 4.8 s. The dearest reply, Claude Fable 5.1's, cost 249 times as much ($0.0874).
The prompt, as sent, and its check
Checked by tests, the same way for every model.
Evaluate an arithmetic expression, no eval (hard)
Write a JavaScript function evaluate(expression) that computes an arithmetic expression given as a string and returns the number. It supports numbers like 3, 0.5 and 12.25; the operators + - * / and ^ (power); parentheses; unary minus; and spaces anywhere. - ^ binds tighter than unary minus and is right-associative, so -2^2 is -4 and 2^3^2 is 512. A unary minus may follow ^, as in 2^-1, which is 0.5. - * and / bind tighter than + and -. Otherwise operators of the same level go left to right, so 8/4/2 is 1. - Throw an Error for input that isn't a valid expression, such as "2 +", "(1" or "1 2". Don't use eval, Function or any library. Reply with the whole function in one ```javascript code block: plain JavaScript for Node.js 22, no imports, no TypeScript.
The reply's evaluate runs against these 15 tests; it passes when all of them do.
evaluate("1 + 2 * 3") // → 7
evaluate("(1 + 2) * 3") // → 9
evaluate("8 / 4 / 2") // → 1
evaluate("10 - 2 - 3") // → 5
evaluate("2 ^ 3 ^ 2") // → 512
evaluate("-2 ^ 2") // → -4
evaluate("(-2) ^ 2") // → 4
evaluate("2 ^ -1") // → 0.5
evaluate("3 - -2") // → 5
evaluate("0.5 * 12.25") // → 6.125
evaluate("-(3 + 1) * 2") // → -8
evaluate("2 * (3 + 4) ^ 2 / 7") // → 14
evaluate("2 +") // throws
evaluate("(1") // throws
evaluate("1 2") // throwsExactly what this prompt's replies are checked against, with every other prompt of our test runs.
Every model's result
All 16 models on this prompt, in catalog order.
| Model | Result | Cost | Time | Reply |
|---|---|---|---|---|
| Claude Fable 5.1Anthropic | Passed: All 15 tests passed. | $0.0874 | 15.7 s | 1,174 tokens |
| Claude Opus 5.5Anthropic | Passed: All 15 tests passed. | $0.0336 | 15.8 s | 1,056 tokens |
| Claude Sonnet 5.5Anthropic | Passed: All 15 tests passed. | $0.0102 | 4.8 s | 827 tokens |
| Claude Sonnet 5Anthropic | Passed: All 15 tests passed. | $0.0226 | 16.9 s | 1,276 tokens |
| Claude Haiku 4.5Anthropic | Failed: 14 of 15 tests passed. First failure: evaluate("-2 ^ 2"): Expected values to be strictly deep-equal: | $0.0056 | 7.6 s | 1,007 tokens |
| GPT-6 AstraOpenAI | Passed: All 15 tests passed. | $0.0375 | 12.0 s | 440 tokens |
| GPT-6 SolOpenAI | Passed: All 15 tests passed. | $0.0089 | 9.7 s | 416 tokens |
| GPT-6 LunaOpenAI | Passed: All 15 tests passed. | $0.00056 | 8.8 s | 552 tokens |
| Gemini 3.1 Pro (preview)Google | Passed: All 15 tests passed. | $0.0351 | 20.6 s | 569 tokens |
| Gemini 3.8 FlashGoogle | Passed: All 15 tests passed. | $0.0045 | 6.7 s | 1,070 tokens |
| DeepSeek V4.1 FlashDeepSeek | Passed: All 15 tests passed. | $0.0028 | 10.4 s | 885 tokens |
| DeepSeek V4 ProDeepSeek | Passed: All 15 tests passed. | $0.0291 | 40.3 s | 849 tokens |
| Grok 4.7xAI | Passed: All 15 tests passed. | $0.0472 | 124.9 s | 653 tokens |
| Kimi K3Moonshot | Passed: All 15 tests passed. | $0.0113 | 9.9 s | 717 tokens |
| GLM 5.3Z.ai | Passed: All 15 tests passed. | $0.0017 | 12.5 s | 509 tokens |
| GLM 5.3 FlashZ.ai | Passed: All 15 tests passed. | $0.00035 | 11.1 s | 477 tokens |
Cost: what OpenRouter charged us for the reply. Time: from sending to the whole reply. Reply: its length in tokens, thinking not counted. In llmwise you pay per message, not per token: each of these replies counted as one message on Pro.
Every reply
The reply that failed first, then the ones that passed, from the cheapest up.
Claude Haiku 4.5
Failed: 14 of 15 tests passed. First failure: evaluate("-2 ^ 2"): Expected values to be strictly deep-equal:
```javascript function evaluate(expression) { const tokens = tokenize(expression); const parser = new Parser(tokens); const result = parser.parseExpression(); if (parser.pos !== tokens.length) { throw new Error("Unexpected tokens after expression"); } return result; } function tokenize(expression) { const tokens = []; let i = 0; while (i < expression.length) { const ch = expression[i]; if (/\s/.test(ch)) { i++; continue; } if (/\d/.test(ch)) { let num = ''; while (i < expression.length && /[\d.]/.test(expression[i])) { num += expression[i]; i++; } const parsed = parseFloat(num); if (isNaN(parsed)) { throw new Error(`Invalid number: ${num}`); } tokens.push({ type: 'NUMBER', value: parsed }); continue; } if ('+-*/^()'.includes(ch)) { tokens.push({ type: ch, value: ch }); i++; continue; } throw new Error(`Unexpected character: ${ch}`); } return tokens; } class Parser { constructor(tokens) { this.tokens = tokens; this.pos = 0; } peek() { return this.tokens[this.pos]; } consume() { return this.tokens[this.pos++]; } parseExpression() { return this.parseAddSub(); } parseAddSub() { let left = this.parseMulDiv(); while (this.peek() && (this.peek().type === '+' || this.peek().type === '-')) { const op = this.consume().type; const right = this.parseMulDiv(); left = op === '+' ? left + right : left - right; } return left; } parseMulDiv() { let left = this.parsePower(); while (this.peek() && (this.peek().type === '*' || this.peek().type === '/')) { const op = this.consume().type; const right = this.parsePower(); left = op === '*' ? left * right : left / right; } return left; } parsePower() { let left = this.parseUnary(); if (this.peek() && this.peek().type === '^') { this.consume(); const right = this.parsePower(); left = Math.pow(left, right); } return left; } parseUnary() { if (this.peek() && this.peek().type === '-') { this.consume(); return -this.parseUnary(); } if (this.peek() && this.peek().type === '+') { this.consume(); return this.parseUnary(); } return this.parsePrimary(); } parsePrimary() { const token = this.peek(); if (!token) { throw new Error("Unexpected end of expression"); } if (token.type === 'NUMBER') { this.consume(); return token.value; } if (token.type === '(') { this.consume(); const result = this.parseExpression(); if (!this.peek() || this.peek().type !== ')') { throw new Error("Missing closing parenthesis"); } this.consume(); return result; } throw new Error(`Unexpected token: ${token.value}`); } } ```599 tokens in, 1,007 out · 7.6 s · $0.0056 · 1 message on Pro · answered by anthropic/claude-haiku-4.5 via Amazon Bedrock ·
GLM 5.3 Flash
Passed: All 15 tests passed.
```javascript function evaluate(expression) { let i = 0; const s = expression; function skipSpaces() { while (i < s.length && s[i] === ' ') i++; } function parseExpr() { let value = parseTerm(); for (;;) { skipSpaces(); if (s[i] === '+') { i++; value += parseTerm(); } else if (s[i] === '-') { i++; value -= parseTerm(); } else return value; } } function parseTerm() { let value = parseUnary(); for (;;) { skipSpaces(); if (s[i] === '*') { i++; value *= parseUnary(); } else if (s[i] === '/') { i++; value /= parseUnary(); } else return value; } } function parseUnary() { skipSpaces(); if (s[i] === '-') { i++; return -parseUnary(); } return parsePower(); } function parsePower() { const base = parsePrimary(); skipSpaces(); if (s[i] === '^') { i++; return Math.pow(base, parseUnary()); // right-assoc, allows 2^-1 } return base; } function parsePrimary() { skipSpaces(); if (s[i] === '(') { i++; const value = parseExpr(); skipSpaces(); if (s[i] !== ')') throw new Error("Expected ')'"); i++; return value; } const start = i; while (i < s.length && s[i] >= '0' && s[i] <= '9') i++; if (i < s.length && s[i] === '.') { i++; while (i < s.length && s[i] >= '0' && s[i] <= '9') i++; } if (i === start || (i === start + 1 && s[start] === '.')) throw new Error('Invalid expression'); return parseFloat(s.slice(start, i)); } const result = parseExpr(); skipSpaces(); if (i !== s.length) throw new Error('Invalid expression'); return result; } ```563 tokens in, 595 out (118 of them reasoning) · 11.1 s · $0.0004 · 1 message on Pro · answered by z-ai/glm-5.3-flash via AtlasCloud ·
GPT-6 Luna
Passed: All 15 tests passed.
```javascript function evaluate(expression) { if (typeof expression !== "string") { throw new Error("Expression must be a string"); } let index = 0; function skipSpaces() { while (index < expression.length && /\s/.test(expression[index])) { index++; } } function parsePrimary() { skipSpaces(); if (expression[index] === "(") { index++; const value = parseExpression(); skipSpaces(); if (expression[index] !== ")") throw new Error("Missing closing parenthesis"); index++; return value; } const start = index; let digitsBefore = 0; while (/\d/.test(expression[index] || "")) { index++; digitsBefore++; } let digitsAfter = 0; if (expression[index] === ".") { index++; while (/\d/.test(expression[index] || "")) { index++; digitsAfter++; } } if (digitsBefore === 0 && digitsAfter === 0) { throw new Error("Expected a number or parenthesized expression"); } return Number(expression.slice(start, index)); } // Unary minus has lower precedence than exponentiation, but is allowed // on an exponent's right-hand side. function parseUnary() { skipSpaces(); if (expression[index] === "-") { index++; return -parseUnary(); } return parsePower(); } function parsePower() { let value = parsePrimary(); skipSpaces(); if (expression[index] === "^") { index++; value **= parseUnary(); } return value; } function parseProduct() { let value = parseUnary(); while (true) { skipSpaces(); const operator = expression[index]; if (operator !== "*" && operator !== "/") break; index++; const right = parseUnary(); value = operator === "*" ? value * right : value / right; } return value; } function parseExpression() { let value = parseProduct(); while (true) { skipSpaces(); const operator = expression[index]; if (operator !== "+" && operator !== "-") break; index++; const right = parseProduct(); value = operator === "+" ? value + right : value - right; } return value; } const result = parseExpression(); skipSpaces(); if (index !== expression.length) throw new Error("Unexpected input"); return result; } ```549 tokens in, 1,007 out (455 of them reasoning) · 8.8 s · $0.0006 · 1 message on Pro · answered by openai/gpt-6-luna via OpenAI ·
GLM 5.3
Passed: All 15 tests passed.
```javascript function evaluate(expression) { if (typeof expression !== 'string') throw new Error('Invalid expression'); const src = expression; let pos = 0; function skipSpaces() { while (pos < src.length && /\s/.test(src[pos])) pos++; } function parseExpr() { let left = parseTerm(); for (;;) { skipSpaces(); if (src[pos] === '+') { pos++; left += parseTerm(); } else if (src[pos] === '-') { pos++; left -= parseTerm(); } else return left; } } function parseTerm() { let left = parseUnary(); for (;;) { skipSpaces(); if (src[pos] === '*') { pos++; left *= parseUnary(); } else if (src[pos] === '/') { pos++; left /= parseUnary(); } else return left; } } function parseUnary() { skipSpaces(); if (src[pos] === '-') { pos++; return -parseUnary(); } return parsePower(); } function parsePower() { const base = parsePrimary(); skipSpaces(); if (src[pos] === '^') { pos++; return Math.pow(base, parseUnary()); // right-assoc, exponent may be unary } return base; } function parsePrimary() { skipSpaces(); if (src[pos] === '(') { pos++; const value = parseExpr(); skipSpaces(); if (src[pos] !== ')') throw new Error('Invalid expression: expected )'); pos++; return value; } if (src[pos] === '-') return parseUnary(); // handled here too for safety const start = pos; while (pos < src.length && /[0-9.]/.test(src[pos])) pos++; if (pos === start) throw new Error('Invalid expression: expected number'); const text = src.slice(start, pos); if (!/^\d+(\.\d+)?$|^\.\d+$/.test(text)) throw new Error('Invalid number: ' + text); return parseFloat(text); } const result = parseExpr(); skipSpaces(); if (pos !== src.length) throw new Error('Invalid expression: unexpected trailing input'); return result; } ```562 tokens in, 594 out (85 of them reasoning) · 12.5 s · $0.0017 · 1 message on Pro · answered by z-ai/glm-5.3 via Reka ·
DeepSeek V4.1 Flash
Passed: All 15 tests passed.
```javascript function evaluate(expression) { if (typeof expression !== 'string') { throw new Error('Expression must be a string'); } // ---- Tokenizer ---- const tokens = []; let i = 0; const isDigit = (c) => c >= '0' && c <= '9'; while (i < expression.length) { const ch = expression[i]; if (ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r') { i++; continue; } if (isDigit(ch) || ch === '.') { const start = i; let dots = 0; while (i < expression.length && (isDigit(expression[i]) || expression[i] === '.')) { if (expression[i] === '.') dots++; i++; } const text = expression.slice(start, i); if (dots > 1 || text === '.') { throw new Error(`Invalid number '${text}'`); } tokens.push({ type: 'num', value: parseFloat(text) }); continue; } if ('+-*/^()'.includes(ch)) { tokens.push({ type: 'op', value: ch }); i++; continue; } throw new Error(`Invalid character '${ch}'`); } // ---- Parser (recursive descent) ---- // expr := term (('+' | '-') term)* // term := unary (('*' | '/') unary)* // unary := ('-' | '+') unary | power // power := primary ('^' unary)? // right-associative, tighter than unary minus // primary:= number | '(' expr ')' let pos = 0; const peek = () => tokens[pos]; function expr() { let value = term(); while (peek() && peek().type === 'op' && (peek().value === '+' || peek().value === '-')) { const op = tokens[pos++].value; const rhs = term(); value = op === '+' ? value + rhs : value - rhs; } return value; } function term() { let value = unary(); while (peek() && peek().type === 'op' && (peek().value === '*' || peek().value === '/')) { const op = tokens[pos++].value; const rhs = unary(); value = op === '*' ? value * rhs : value / rhs; } return value; } function unary() { const t = peek(); if (t && t.type === 'op' && t.value === '-') { pos++; return -unary(); } if (t && t.type === 'op' && t.value === '+') { pos++; return unary(); } return power(); } function power() { const base = primary(); if (peek() && peek().type === 'op' && peek().value === '^') { pos++; const exponent = unary(); // right-associative, allows unary minus after ^ return Math.pow(base, exponent); } return base; } function primary() { const t = peek(); if (!t) throw new Error('Unexpected end of expression'); if (t.type === 'num') { pos++; return t.value; } if (t.type === 'op' && t.value === '(') { pos++; const value = expr(); const closing = peek(); if (!closing || closing.type !== 'op' || closing.value !== ')') { throw new Error("Expected ')'"); } pos++; return value; } throw new Error(`Unexpected token '${t.value}'`); } const result = expr(); if (pos !== tokens.length) { throw new Error(`Unexpected token '${tokens[pos].value}'`); } return result; } ```591 tokens in, 2,216 out (1,331 of them reasoning) · 10.4 s · $0.0028 · 1 message on Pro · answered by deepseek/deepseek-v4.1-flash via Parasail ·
Gemini 3.8 Flash
Passed: All 15 tests passed.
```javascript function evaluate(expression) { // Tokenize the expression const tokens = []; let i = 0; const n = expression.length; while (i < n) { const ch = expression[i]; if (/\s/.test(ch)) { i++; continue; } if (/[0-9.]/.test(ch)) { let start = i; let dotCount = 0; while (i < n && /[0-9.]/.test(expression[i])) { if (expression[i] === '.') dotCount++; i++; } if (dotCount > 1) { throw new Error(`Invalid number format at index ${start}`); } const numStr = expression.slice(start, i); if (numStr === '.') { throw new Error(`Invalid single dot at index ${start}`); } tokens.push({ type: 'NUMBER', value: parseFloat(numStr) }); continue; } if ('+-*/^()'.includes(ch)) { tokens.push({ type: ch, value: ch }); i++; continue; } throw new Error(`Unexpected character '${ch}' at index ${i}`); } let pos = 0; function peek() { return tokens[pos]; } function consume(expectedType) { const token = tokens[pos]; if (!token || (expectedType && token.type !== expectedType)) { throw new Error(`Unexpected token at position ${pos}`); } pos++; return token; } // Grammar with precedence: // Expr -> AddSub // AddSub -> MulDiv (('+' | '-') MulDiv)* // MulDiv -> Unary (('*' | '/') Unary)* // Unary -> '-' Unary | Power // Power -> Primary ('^' (Unary | Power))? -- right associative, handles 2^-1 and -2^2 // Primary -> NUMBER | '(' Expr ')' function parseExpr() { return parseAddSub(); } function parseAddSub() { let left = parseMulDiv(); while (pos < tokens.length && (tokens[pos].type === '+' || tokens[pos].type === '-')) { const op = consume().type; const right = parseMulDiv(); left = op === '+' ? left + right : left - right; } return left; } function parseMulDiv() { let left = parseUnary(); while (pos < tokens.length && (tokens[pos].type === '*' || tokens[pos].type === '/')) { const op = consume().type; const right = parseUnary(); if (op === '/') { left = left / right; } else { left = left * right; } } return left; } function parseUnary() { if (pos < tokens.length && tokens[pos].type === '-') { consume('-'); return -parseUnary(); } if (pos < tokens.length && tokens[pos].type === '+') { consume('+'); return parseUnary(); } return parsePower(); } function parsePower() { let left = parsePrimary(); if (pos < tokens.length && tokens[pos].type === '^') { consume('^'); // Right-hand side allows unary minus (e.g. 2^-1) or another power const right = parseUnary(); return Math.pow(left, right); } return left; } function parsePrimary() { const token = peek(); if (!token) { throw new Error('Unexpected end of input'); } if (token.type === 'NUMBER') { consume('NUMBER'); return token.value; } if (token.type === '(') { consume('('); const val = parseExpr(); consume(')'); return val; } throw new Error(`Unexpected token '${token.value}' at position ${pos}`); } if (tokens.length === 0) { throw new Error('Empty expression'); } const result = parseExpr(); if (pos < tokens.length) { throw new Error(`Unexpected token at position ${pos}`); } return result; } ```587 tokens in, 1,070 out · 6.7 s · $0.0045 · 1 message on Pro · answered by google/gemini-3.8-flash via Google ·
GPT-6 Sol
Passed: All 15 tests passed.
```javascript function evaluate(expression) { if (typeof expression !== "string") { throw new Error("Expression must be a string"); } let pos = 0; const numberPattern = /\d+(?:\.\d+)?/y; function peek() { while (pos < expression.length && /\s/.test(expression[pos])) pos++; return expression[pos]; } function primary() { if (peek() === "(") { pos++; const value = sum(); if (peek() !== ")") throw new Error("Missing closing parenthesis"); pos++; return value; } peek(); numberPattern.lastIndex = pos; const match = numberPattern.exec(expression); if (!match) throw new Error("Expected a number or '('"); pos = numberPattern.lastIndex; return Number(match[0]); } function power() { const left = primary(); if (peek() === "^") { pos++; return left ** unary(); } return left; } function unary() { if (peek() === "-") { pos++; return -unary(); } return power(); } function product() { let value = unary(); while (true) { const op = peek(); if (op !== "*" && op !== "/") return value; pos++; const right = unary(); value = op === "*" ? value * right : value / right; } } function sum() { let value = product(); while (true) { const op = peek(); if (op !== "+" && op !== "-") return value; pos++; const right = product(); value = op === "+" ? value + right : value - right; } } const result = sum(); if (peek() !== undefined) throw new Error("Unexpected input"); return result; } ```549 tokens in, 785 out (369 of them reasoning) · 9.7 s · $0.0089 · 1 message on Pro · answered by openai/gpt-6-sol via OpenAI ·
Claude Sonnet 5.5
Passed: All 15 tests passed.
```javascript function evaluate(expression) { if (typeof expression !== 'string') throw new Error('Expression must be a string'); const s = expression; let pos = 0; function skip() { while (pos < s.length && /\s/.test(s[pos])) pos++; } function peek() { skip(); return pos < s.length ? s[pos] : null; } // expr := term (('+'|'-') term)* function parseExpr() { let left = parseTerm(); for (;;) { const c = peek(); if (c === '+') { pos++; left = left + parseTerm(); } else if (c === '-') { pos++; left = left - parseTerm(); } else return left; } } // term := unary (('*'|'/') unary)* function parseTerm() { let left = parseUnary(); for (;;) { const c = peek(); if (c === '*') { pos++; left = left * parseUnary(); } else if (c === '/') { pos++; left = left / parseUnary(); } else return left; } } // unary := '-' unary | power (also allow unary plus? not required -> no) function parseUnary() { if (peek() === '-') { pos++; return -parseUnary(); } return parsePower(); } // power := primary ('^' unary)? right-assoc; exponent may have unary minus function parsePower() { const base = parsePrimary(); if (peek() === '^') { pos++; const exp = parseUnary(); return Math.pow(base, exp); } return base; } function parsePrimary() { const c = peek(); if (c === null) throw new Error('Unexpected end of expression'); if (c === '(') { pos++; const v = parseExpr(); if (peek() !== ')') throw new Error('Missing closing parenthesis'); pos++; return v; } const m = /^(\d+(\.\d+)?|\.\d+)/.exec(s.slice(pos)); if (m) { pos += m[0].length; return parseFloat(m[0]); } throw new Error('Unexpected character: ' + c); } const result = parseExpr(); if (peek() !== null) throw new Error('Unexpected token: ' + s[pos]); return result; } ```764 tokens in, 827 out · 4.8 s · $0.0102 · 1 message on Pro · answered by anthropic/claude-sonnet-5.5 via Anthropic ·
Kimi K3
Passed: All 15 tests passed.
```javascript function evaluate(expression) { if (typeof expression !== "string") { throw new Error("Input must be a string"); } let pos = 0; function skipSpaces() { while (pos < expression.length && expression[pos] === " ") { pos++; } } function peek() { skipSpaces(); return pos < expression.length ? expression[pos] : null; } function parseExpression() { let value = parseTerm(); for (;;) { const ch = peek(); if (ch === "+") { pos++; value += parseTerm(); } else if (ch === "-") { pos++; value -= parseTerm(); } else { return value; } } } function parseTerm() { let value = parseUnary(); for (;;) { const ch = peek(); if (ch === "*") { pos++; value *= parseUnary(); } else if (ch === "/") { pos++; value /= parseUnary(); } else { return value; } } } function parseUnary() { const ch = peek(); if (ch === "-") { pos++; return -parseUnary(); } if (ch === "+") { pos++; return parseUnary(); } return parsePower(); } function parsePower() { const base = parsePrimary(); if (peek() === "^") { pos++; const exponent = parseUnary(); // right-associative, allows 2^-1 return Math.pow(base, exponent); } return base; } function parsePrimary() { const ch = peek(); if (ch === null) { throw new Error("Unexpected end of expression"); } if (ch === "(") { pos++; const value = parseExpression(); if (peek() !== ")") { throw new Error("Missing closing parenthesis"); } pos++; return value; } return parseNumber(); } function parseNumber() { skipSpaces(); const start = pos; let sawDigit = false; while (pos < expression.length && expression[pos] >= "0" && expression[pos] <= "9") { pos++; sawDigit = true; } if (pos < expression.length && expression[pos] === ".") { pos++; while (pos < expression.length && expression[pos] >= "0" && expression[pos] <= "9") { pos++; sawDigit = true; } } if (!sawDigit) { throw new Error("Expected a number at position " + start); } return Number(expression.slice(start, pos)); } const result = parseExpression(); if (peek() !== null) { throw new Error("Unexpected character '" + expression[pos] + "' at position " + pos); } return result; } ``` A recursive-descent parser with the precedence levels: `+`/`-` (lowest), then `*`/`/`, then unary minus, then `^` (right-associative, binds tighter than unary minus, and its exponent is parsed as unary so `2^-1` works), then numbers and parentheses. Leftover characters or missing operands throw an `Error`.636 tokens in, 816 out (99 of them reasoning) · 9.9 s · $0.0113 · 1 message on Pro · answered by moonshotai/kimi-k3 via Phala ·
Claude Sonnet 5
Passed: All 15 tests passed.
```javascript function evaluate(expression) { // ---- Tokenizer ---- const tokens = []; let i = 0; const s = expression; while (i < s.length) { const c = s[i]; if (c === ' ' || c === '\t' || c === '\n' || c === '\r') { i++; continue; } if ('+-*/^()'.includes(c)) { tokens.push(c); i++; continue; } if ((c >= '0' && c <= '9') || c === '.') { let start = i; let seenDot = false; let seenDigit = false; while (i < s.length && ((s[i] >= '0' && s[i] <= '9') || s[i] === '.')) { if (s[i] === '.') { if (seenDot) break; seenDot = true; } else { seenDigit = true; } i++; } const raw = s.slice(start, i); if (!seenDigit || !/^\d*\.?\d*$/.test(raw)) { throw new Error(`Invalid number: "${raw}"`); } tokens.push({ type: 'num', value: parseFloat(raw) }); continue; } throw new Error(`Unexpected character "${c}" at position ${i}`); } // ---- Parser ---- let pos = 0; function peek() { return tokens[pos]; } function next() { return tokens[pos++]; } function expect(tok) { const t = next(); if (t !== tok) { throw new Error(`Expected "${tok}" but got "${t === undefined ? 'end of input' : (typeof t === 'object' ? t.value : t)}"`); } } function parseExpr() { let value = parseTerm(); while (peek() === '+' || peek() === '-') { const op = next(); const rhs = parseTerm(); value = op === '+' ? value + rhs : value - rhs; } return value; } function parseTerm() { let value = parseUnary(); while (peek() === '*' || peek() === '/') { const op = next(); const rhs = parseUnary(); if (op === '*') { value = value * rhs; } else { value = value / rhs; } } return value; } function parseUnary() { if (peek() === '-') { next(); return -parseUnary(); } if (peek() === '+') { next(); return parseUnary(); } return parsePower(); } function parsePower() { const base = parseAtom(); if (peek() === '^') { next(); const exponent = parseUnary(); // right-associative, allows unary minus return Math.pow(base, exponent); } return base; } function parseAtom() { const t = peek(); if (t === undefined) { throw new Error('Unexpected end of input'); } if (t === '(') { next(); const value = parseExpr(); expect(')'); return value; } if (typeof t === 'object' && t.type === 'num') { next(); return t.value; } throw new Error(`Unexpected token "${typeof t === 'object' ? t.value : t}"`); } if (tokens.length === 0) { throw new Error('Empty expression'); } const result = parseExpr(); if (pos !== tokens.length) { const remaining = tokens[pos]; throw new Error(`Unexpected token "${typeof remaining === 'object' ? remaining.value : remaining}" after expression`); } return result; } ```760 tokens in, 2,110 out (834 of them reasoning) · 16.9 s · $0.0226 · 1 message on Pro · answered by anthropic/claude-sonnet-5 via Claude Platform on AWS ·
DeepSeek V4 Pro
Passed: All 15 tests passed.
```javascript function evaluate(expression) { function tokenize(input) { const tokens = []; let i = 0; while (i < input.length) { const ch = input[i]; if (/\s/.test(ch)) { i++; continue; } if (ch >= '0' && ch <= '9') { const start = i; while (i < input.length && input[i] >= '0' && input[i] <= '9') { i++; } if (i < input.length && input[i] === '.') { i++; if (i < input.length && input[i] >= '0' && input[i] <= '9') { while (i < input.length && input[i] >= '0' && input[i] <= '9') { i++; } } else { throw new Error('Invalid number'); } } tokens.push({ type: 'number', value: parseFloat(input.slice(start, i)) }); continue; } if (ch === '+' || ch === '-' || ch === '*' || ch === '/' || ch === '^') { tokens.push({ type: 'op', value: ch }); i++; continue; } if (ch === '(') { tokens.push({ type: 'lparen' }); i++; continue; } if (ch === ')') { tokens.push({ type: 'rparen' }); i++; continue; } throw new Error(`Invalid character "${ch}"`); } return tokens; } const tokens = tokenize(expression); let pos = 0; function peek() { return tokens[pos]; } function next() { return tokens[pos++]; } function isOp(value) { const token = peek(); return token !== undefined && token.type === 'op' && token.value === value; } function parsePrimary() { const token = peek(); if (token === undefined) { throw new Error('Unexpected end of expression'); } if (token.type === 'number') { next(); return token.value; } if (token.type === 'lparen') { next(); const value = parseExpr(); const closing = peek(); if (closing === undefined || closing.type !== 'rparen') { throw new Error('Expected closing parenthesis'); } next(); return value; } throw new Error(`Unexpected token "${token.value}"`); } function parseExponent() { let base = parsePrimary(); if (isOp('^')) { next(); const exponent = parseUnary(); base = Math.pow(base, exponent); } return base; } function parseUnary() { if (isOp('-')) { next(); const operand = parseUnary(); return -operand; } return parseExponent(); } function parseTerm() { let left = parseUnary(); while (true) { if (isOp('*')) { next(); const right = parseUnary(); left *= right; } else if (isOp('/')) { next(); const right = parseUnary(); left /= right; } else { break; } } return left; } function parseExpr() { let left = parseTerm(); while (true) { if (isOp('+')) { next(); const right = parseTerm(); left += right; } else if (isOp('-')) { next(); const right = parseTerm(); left -= right; } else { break; } } return left; } const result = parseExpr(); if (pos !== tokens.length) { throw new Error('Unexpected trailing tokens'); } return result; } ```563 tokens in, 8,285 out (7,436 of them reasoning) · 40.3 s · $0.0291 · 1 message on Pro · answered by deepseek/deepseek-v4-pro-0813 via Wafer ·
Claude Opus 5.5
Passed: All 15 tests passed.
```javascript function evaluate(expression) { if (typeof expression !== "string") { throw new Error("Expression must be a string"); } // Tokenizer const tokens = []; const numberRe = /\d+(?:\.\d+)?|\.\d+/y; let i = 0; while (i < expression.length) { const ch = expression[i]; if (/\s/.test(ch)) { i++; continue; } if ("+-*/^()".includes(ch)) { tokens.push({ type: ch }); i++; continue; } numberRe.lastIndex = i; const m = numberRe.exec(expression); if (m) { tokens.push({ type: "num", value: parseFloat(m[0]) }); i += m[0].length; continue; } throw new Error(`Unexpected character '${ch}' at position ${i}`); } // Recursive descent parser let pos = 0; const peek = () => tokens[pos]; const accept = (type) => { if (tokens[pos] && tokens[pos].type === type) { pos++; return true; } return false; }; // expr := term (('+' | '-') term)* function parseExpr() { let value = parseTerm(); for (;;) { if (accept("+")) value += parseTerm(); else if (accept("-")) value -= parseTerm(); else return value; } } // term := unary (('*' | '/') unary)* function parseTerm() { let value = parseUnary(); for (;;) { if (accept("*")) value *= parseUnary(); else if (accept("/")) value /= parseUnary(); else return value; } } // unary := '-' unary | power function parseUnary() { if (accept("-")) return -parseUnary(); return parsePower(); } // power := primary ('^' unary)? (right-associative; exponent may be negated) function parsePower() { const base = parsePrimary(); if (accept("^")) { const exponent = parseUnary(); return Math.pow(base, exponent); } return base; } // primary := number | '(' expr ')' function parsePrimary() { const tok = peek(); if (!tok) throw new Error("Unexpected end of expression"); if (tok.type === "num") { pos++; return tok.value; } if (accept("(")) { const value = parseExpr(); if (!accept(")")) throw new Error("Expected ')'"); return value; } throw new Error(`Unexpected token '${tok.type}'`); } if (tokens.length === 0) throw new Error("Empty expression"); const result = parseExpr(); if (pos !== tokens.length) { const tok = tokens[pos]; throw new Error( `Unexpected token '${tok.type === "num" ? tok.value : tok.type}'` ); } return result; } ```762 tokens in, 1,491 out (435 of them reasoning) · 15.8 s · $0.0336 · 1 message on Pro · answered by anthropic/claude-opus-5.5 via Claude Platform on AWS ·
Gemini 3.1 Pro
Passed: All 15 tests passed.
```javascript function evaluate(expression) { let pos = 0; function peek() { while (pos < expression.length && expression[pos] === ' ') { pos++; } return pos < expression.length ? expression[pos] : null; } function parseExpr() { let left = parseTerm(); while (true) { let char = peek(); if (char === '+' || char === '-') { pos++; let right = parseTerm(); if (char === '+') left += right; else left -= right; } else { break; } } return left; } function parseTerm() { let left = parseFactor(); while (true) { let char = peek(); if (char === '*' || char === '/') { pos++; let right = parseFactor(); if (char === '*') left *= right; else left /= right; } else { break; } } return left; } function parseFactor() { let char = peek(); if (char === '-') { pos++; return -parseFactor(); } return parsePower(); } function parsePower() { let left = parsePrimary(); let char = peek(); if (char === '^') { pos++; let right = parseFactor(); return Math.pow(left, right); } return left; } function parsePrimary() { let char = peek(); if (char === null) { throw new Error("Unexpected end of expression"); } if (char === '(') { pos++; let val = parseExpr(); if (peek() !== ')') { throw new Error("Missing closing parenthesis"); } pos++; return val; } let match = expression.slice(pos).match(/^\d+(\.\d+)?/); if (!match) { throw new Error(`Invalid character at position ${pos}`); } pos += match[0].length; return parseFloat(match[0]); } let result = parseExpr(); if (peek() !== null) { throw new Error(`Unexpected character at position ${pos}`); } return result; } ```587 tokens in, 2,831 out (2,262 of them reasoning) · 20.6 s · $0.0351 · 1 message on Pro · answered by google/gemini-3.1-pro-preview via Google ·
GPT-6 Astra
Passed: All 15 tests passed.
```javascript function evaluate(expression) { if (typeof expression !== "string") { throw new Error("Expression must be a string"); } let pos = 0; function skipSpaces() { while (pos < expression.length && /\s/.test(expression[pos])) { pos++; } } function consume(character) { skipSpaces(); if (expression[pos] === character) { pos++; return true; } return false; } function fail(message) { throw new Error(`${message} at position ${pos}`); } function parsePrimary() { if (consume("(")) { const value = parseSum(); if (!consume(")")) fail("Expected ')'"); return value; } skipSpaces(); const match = /^(?:\d+(?:\.\d*)?|\.\d+)/.exec(expression.slice(pos)); if (!match) fail("Expected a number or '('"); pos += match[0].length; return Number(match[0]); } function parsePower() { const base = parsePrimary(); // Parsing the exponent as unary allows 2^-1 and makes ^ right-associative. return consume("^") ? base ** parseUnary() : base; } function parseUnary() { // Power binds more tightly than unary minus. return consume("-") ? -parseUnary() : parsePower(); } function parseProduct() { let value = parseUnary(); while (true) { if (consume("*")) value *= parseUnary(); else if (consume("/")) value /= parseUnary(); else return value; } } function parseSum() { let value = parseProduct(); while (true) { if (consume("+")) value += parseProduct(); else if (consume("-")) value -= parseProduct(); else return value; } } const result = parseSum(); skipSpaces(); if (pos !== expression.length) fail("Unexpected input"); return result; } ```549 tokens in, 640 out (200 of them reasoning) · 12.0 s · $0.0375 · 1 message on Pro · answered by openai/gpt-6-astra via OpenAI ·
Grok 4.7
Passed: All 15 tests passed.
```javascript function evaluate(expression) { if (typeof expression !== "string") { throw new Error("Invalid expression"); } const s = expression; let i = 0; function skip() { while (i < s.length && (s[i] === " " || s[i] === "\t" || s[i] === "\n" || s[i] === "\r" || s[i] === "\f" || s[i] === "\v")) { i++; } } function parseAdd() { let left = parseMul(); for (;;) { skip(); const op = s[i]; if (op !== "+" && op !== "-") break; i++; const right = parseMul(); left = op === "+" ? left + right : left - right; } return left; } function parseMul() { let left = parseUnary(); for (;;) { skip(); const op = s[i]; if (op !== "*" && op !== "/") break; i++; const right = parseUnary(); left = op === "*" ? left * right : left / right; } return left; } function parseUnary() { skip(); if (s[i] === "-") { i++; return -parseUnary(); } return parsePow(); } function parsePow() { const base = parsePrimary(); skip(); if (s[i] === "^") { i++; return base ** parseUnary(); } return base; } function parsePrimary() { skip(); if (s[i] === "(") { i++; const value = parseAdd(); skip(); if (s[i] !== ")") throw new Error("Invalid expression"); i++; return value; } return parseNumber(); } function parseNumber() { skip(); if (i >= s.length || s[i] < "0" || s[i] > "9") { throw new Error("Invalid expression"); } const start = i; while (i < s.length && s[i] >= "0" && s[i] <= "9") i++; if (s[i] === ".") { i++; if (i >= s.length || s[i] < "0" || s[i] > "9") { throw new Error("Invalid expression"); } while (i < s.length && s[i] >= "0" && s[i] <= "9") i++; } return Number(s.slice(start, i)); } const value = parseAdd(); skip(); if (i !== s.length) throw new Error("Invalid expression"); return value; } ```1,785 tokens in, 9,532 out (8,879 of them reasoning) · 124.9 s · $0.0472 · 1 message on Pro · answered by x-ai/grok-4.7 via xAI ·
Claude Fable 5.1
Passed: All 15 tests passed.
```javascript function evaluate(expression) { if (typeof expression !== "string") throw new Error("Expression must be a string"); // ---- Tokenizer ---- const tokens = []; let i = 0; while (i < expression.length) { const ch = expression[i]; if (ch === " " || ch === "\t" || ch === "\n" || ch === "\r") { i++; continue; } if (ch >= "0" && ch <= "9") { let start = i; while (i < expression.length && expression[i] >= "0" && expression[i] <= "9") i++; if (expression[i] === ".") { i++; if (!(expression[i] >= "0" && expression[i] <= "9")) { throw new Error(`Invalid number at position ${start}`); } while (i < expression.length && expression[i] >= "0" && expression[i] <= "9") i++; } tokens.push({ type: "num", value: parseFloat(expression.slice(start, i)), pos: start }); continue; } if ("+-*/^()".includes(ch)) { tokens.push({ type: ch, pos: i }); i++; continue; } throw new Error(`Unexpected character '${ch}' at position ${i}`); } tokens.push({ type: "end", pos: expression.length }); // ---- Parser ---- let p = 0; const peek = () => tokens[p]; const next = () => tokens[p++]; const fail = (tok) => new Error( tok.type === "end" ? "Unexpected end of expression" : `Unexpected token '${tok.type === "num" ? tok.value : tok.type}' at position ${tok.pos}` ); // expr := term (('+'|'-') term)* function parseExpr() { let value = parseTerm(); while (peek().type === "+" || peek().type === "-") { const op = next().type; const rhs = parseTerm(); value = op === "+" ? value + rhs : value - rhs; } return value; } // term := unary (('*'|'/') unary)* function parseTerm() { let value = parseUnary(); while (peek().type === "*" || peek().type === "/") { const op = next().type; const rhs = parseUnary(); value = op === "*" ? value * rhs : value / rhs; } return value; } // unary := '-' unary | power function parseUnary() { if (peek().type === "-") { next(); return -parseUnary(); } return parsePower(); } // power := atom ('^' unary)? (right-associative; exponent may carry unary minus) function parsePower() { const base = parseAtom(); if (peek().type === "^") { next(); const exponent = parseUnary(); return Math.pow(base, exponent); } return base; } // atom := number | '(' expr ')' function parseAtom() { const tok = next(); if (tok.type === "num") return tok.value; if (tok.type === "(") { const value = parseExpr(); const close = next(); if (close.type !== ")") throw fail(close); return value; } throw fail(tok); } const result = parseExpr(); if (peek().type !== "end") throw fail(peek()); return result; } ```762 tokens in, 1,561 out (387 of them reasoning) · 15.7 s · $0.0874 · 1 message on Pro · answered by anthropic/claude-fable-5.1 via Anthropic ·
More coding prompts
The other coding prompts, each with every model's reply, and the results across all five.
Questions
Which AI does best on “Evaluate an arithmetic expression, no eval”?
15 of 16 models passed this coding prompt's check (tests); Claude Haiku 4.5 didn't. The cheapest reply that passed was GLM 5.3 Flash's, at $0.00035; the fastest, Claude Sonnet 5.5's in 4.8 s. The dearest reply, Claude Fable 5.1's, cost 249 times as much ($0.0874).
What does a reply to “Evaluate an arithmetic expression, no eval” cost?
Through the models' APIs, what OpenRouter charged us ran from $0.00035 (GLM 5.3 Flash) to $0.0874 (Claude Fable 5.1) for this prompt. In llmwise you don't pay by the token: a reply like these counts as one message on Pro, whichever model answers.
Claude, GPT, Gemini, DeepSeek, Grok, Kimi, and GLM, in one chat.
See what a message costs before you send it. Free is 5 messages to try; sign in with an email link, no password or card.