Tested prompt · Coding
Evaluate an arithmetic expression, no eval: every AI model's reply, tested
We sent this hard coding prompt to all 20 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 20 of our test runs on , through OpenRouter with the app's own prompt and settings. Updated .
Short answer
18 of 20 models passed this coding prompt's check (tests); Claude Haiku 4.5 and Mistral Large 4 didn't. The cheapest reply that passed was GLM 5.3 Flash's, at $0.00035; the fastest, Claude Haiku 5.5's in 3.9 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 20 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 5.5Anthropic | Passed: All 15 tests passed. | $0.00063 | 3.9 s | 1,074 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.1 SolOpenAI | Passed: All 15 tests passed. | $0.0037 | 7.8 s | 404 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 4 ArgonGoogle | Passed: All 15 tests passed. | $0.0050 | 9.7 s | 841 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.0030 | 5.8 s | 951 tokens |
| DeepSeek V4 ProDeepSeek | Passed: All 15 tests passed. | $0.0440 | 145.7 s | 621 tokens |
| Grok 4.7xAI | Passed: All 15 tests passed. | $0.0574 | 110.1 s | 613 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 |
| Mistral Large 4Mistral | Failed: No answer within Pro's reply limit of 8,000 tokens: the model spent them all reasoning. | $0.0171 | 95.6 s | 1,286 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 2 replies 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 ·
Mistral Large 4
Failed: No answer within Pro's reply limit of 8,000 tokens: the model spent them all reasoning.
(no reply)
562 tokens in, 8,000 out (6,714 of them reasoning) · 95.6 s · $0.0171 · 1 message on Pro · answered by mistralai/mistral-large-4-0 via Mistral ·
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 ·
Claude Haiku 5.5
Passed: All 15 tests passed.
```javascript function evaluate(expression) { const s = String(expression); const tokens = []; let i = 0; while (i < s.length) { const c = s[i]; if (c === ' ' || c === '\t' || c === '\n' || c === '\r') { i++; continue; } if ((c >= '0' && c <= '9') || c === '.') { let j = i; while (j < s.length && ((s[j] >= '0' && s[j] <= '9') || s[j] === '.')) j++; const text = s.slice(i, j); if (!/^(\d+\.?\d*|\.\d+)$/.test(text)) throw new Error(`Invalid number "${text}"`); tokens.push({ type: 'num', value: Number(text) }); i = j; continue; } if ('+-*/^()'.includes(c)) { tokens.push({ type: c }); i++; continue; } throw new Error(`Unexpected character "${c}"`); } let pos = 0; const peek = () => tokens[pos] ? tokens[pos].type : null; const next = () => tokens[pos++]; // expr := term (('+'|'-') term)* function parseExpr() { let value = parseTerm(); while (peek() === '+' || peek() === '-') { 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() === '*' || peek() === '/') { const op = next().type; const rhs = parseUnary(); value = op === '*' ? value * rhs : value / rhs; } return value; } // unary := '-' unary | power function parseUnary() { if (peek() === '-') { next(); return -parseUnary(); } return parsePower(); } // power := primary ('^' unary)? (right-associative; exponent may be signed) function parsePower() { const base = parsePrimary(); if (peek() === '^') { next(); const exp = parseUnary(); return Math.pow(base, exp); } return base; } // primary := number | '(' expr ')' function parsePrimary() { const t = tokens[pos]; if (!t) throw new Error('Unexpected end of expression'); if (t.type === 'num') { pos++; return t.value; } if (t.type === '(') { pos++; const value = parseExpr(); if (peek() !== ')') throw new Error('Expected ")"'); pos++; return value; } throw new Error(`Unexpected token "${t.type}"`); } if (tokens.length === 0) throw new Error('Empty expression'); const result = parseExpr(); if (pos !== tokens.length) throw new Error(`Unexpected token "${tokens[pos].type}"`); return result; } ```763 tokens in, 1,074 out · 3.9 s · $0.0006 · 1 message on Pro · answered by anthropic/claude-haiku-5.5 via Anthropic ·
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') { i++; continue; } // number: digits with an optional single decimal point (at least one digit) if (isDigit(ch) || ch === '.') { let j = i; let digits = 0; while (j < expression.length && isDigit(expression[j])) { j++; digits++; } if (j < expression.length && expression[j] === '.') { j++; while (j < expression.length && isDigit(expression[j])) { j++; digits++; } } if (digits === 0) { throw new Error('Invalid number in expression'); } tokens.push({ type: 'num', value: parseFloat(expression.slice(i, j)) }); i = j; continue; } if ('+-*/^()'.indexOf(ch) !== -1) { tokens.push({ type: ch }); i++; continue; } throw new Error('Unexpected character: ' + ch); } if (tokens.length === 0) { throw new Error('Empty expression'); } // ---- Parser (recursive descent) ---- let pos = 0; const peek = () => tokens[pos]; const isOp = (tok, ch) => tok !== undefined && tok.type === ch; // expr := term (('+' | '-') term)* left-associative function parseExpression() { let value = parseTerm(); while (isOp(peek(), '+') || isOp(peek(), '-')) { const op = tokens[pos++].type; const rhs = parseTerm(); value = op === '+' ? value + rhs : value - rhs; } return value; } // term := unary (('*' | '/') unary)* left-associative function parseTerm() { let value = parseUnary(); while (isOp(peek(), '*') || isOp(peek(), '/')) { const op = tokens[pos++].type; const rhs = parseUnary(); value = op === '*' ? value * rhs : value / rhs; } return value; } // unary := ('-' | '+') unary | power // unary minus is looser than '^', so -2^2 === -(2^2) === -4 function parseUnary() { if (isOp(peek(), '-')) { pos++; return -parseUnary(); } if (isOp(peek(), '+')) { pos++; return parseUnary(); } return parsePower(); } // power := primary ('^' unary)? right-associative // the exponent is a unary, which permits 2^-1 and 2^3^2 = 2^(3^2) function parsePower() { const base = parsePrimary(); if (isOp(peek(), '^')) { pos++; const exponent = parseUnary(); return Math.pow(base, exponent); } return base; } // primary := number | '(' expr ')' function parsePrimary() { const tok = peek(); if (tok === undefined) { throw new Error('Unexpected end of expression'); } if (tok.type === 'num') { pos++; return tok.value; } if (tok.type === '(') { pos++; const value = parseExpression(); if (!isOp(peek(), ')')) { throw new Error('Missing closing parenthesis'); } pos++; return value; } throw new Error('Unexpected token: ' + tok.type); } const result = parseExpression(); if (pos !== tokens.length) { throw new Error('Unexpected token: ' + tokens[pos].type); } return result; } ```591 tokens in, 2,442 out (1,491 of them reasoning) · 5.8 s · $0.0030 · 1 message on Pro · answered by deepseek/deepseek-v4.1-flash via Together ·
GPT-6.1 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; function skipSpaces() { while (pos < expression.length && /\s/.test(expression[pos])) { pos++; } } function take(char) { skipSpaces(); if (expression[pos] === char) { pos++; return true; } return false; } function invalid() { throw new Error(`Invalid expression at position ${pos}`); } function primary() { skipSpaces(); if (take("(")) { const value = additive(); if (!take(")")) invalid(); return value; } const match = /^(?:\d+(?:\.\d*)?|\.\d+)/.exec(expression.slice(pos)); if (!match) invalid(); pos += match[0].length; return Number(match[0]); } function power() { const base = primary(); // Parsing the exponent as unary permits 2^-1 and right-associative powers. return take("^") ? base ** unary() : base; } function unary() { return take("-") ? -unary() : power(); } function multiplicative() { let value = unary(); while (true) { if (take("*")) value *= unary(); else if (take("/")) value /= unary(); else return value; } } function additive() { let value = multiplicative(); while (true) { if (take("+")) value += multiplicative(); else if (take("-")) value -= multiplicative(); else return value; } } const result = additive(); skipSpaces(); if (pos !== expression.length) invalid(); return result; } ```551 tokens in, 632 out (228 of them reasoning) · 7.8 s · $0.0037 · 1 message on Pro · answered by openai/gpt-6.1-sol via OpenAI ·
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 ·
Gemini 4 Argon
Passed: All 15 tests passed.
```javascript function evaluate(expression) { if (typeof expression !== 'string') { throw new Error('Invalid expression'); } const tokens = []; 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; } if (/[0-9]/.test(ch)) { let numStr = ''; let hasDot = false; while (i < expression.length && (/[0-9]/.test(expression[i]) || expression[i] === '.')) { if (expression[i] === '.') { if (hasDot) throw new Error('Invalid number'); hasDot = true; } numStr += expression[i]; i++; } if (numStr.endsWith('.')) { throw new Error('Invalid number'); } tokens.push({ type: 'num', value: Number(numStr) }); continue; } throw new Error(`Unexpected character: ${ch}`); } let pos = 0; function peek() { return tokens[pos]; } function consume(expectedType) { const tok = tokens[pos]; if (!tok || (expectedType && tok.type !== expectedType)) { throw new Error('Unexpected token'); } pos++; return tok; } function parseExpression() { let val = parseTerm(); while (peek() && (peek().type === '+' || peek().type === '-')) { const op = consume().type; const right = parseTerm(); val = op === '+' ? val + right : val - right; } return val; } function parseTerm() { let val = parseUnary(); while (peek() && (peek().type === '*' || peek().type === '/')) { const op = consume().type; const right = parseUnary(); val = op === '*' ? val * right : val / right; } return val; } function parseUnary() { if (peek() && peek().type === '-') { consume('-'); return -parseUnary(); } return parsePower(); } function parsePower() { const base = parsePrimary(); if (peek() && peek().type === '^') { consume('^'); const exp = parseUnary(); return Math.pow(base, exp); } return base; } function parsePrimary() { const tok = peek(); if (!tok) { throw new Error('Unexpected end of expression'); } if (tok.type === 'num') { consume('num'); return tok.value; } if (tok.type === '(') { consume('('); const val = parseExpression(); consume(')'); return val; } throw new Error(`Unexpected token: ${tok.type}`); } if (tokens.length === 0) { throw new Error('Empty expression'); } const result = parseExpression(); if (pos < tokens.length) { throw new Error('Unexpected trailing tokens'); } return result; } ```809 tokens in, 841 out · 9.7 s · $0.0050 · 1 message on Pro · answered by google/gemini-4-argon via Google AI Studio ·
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 ·
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 ·
DeepSeek V4 Pro
Passed: All 15 tests passed.
```javascript function evaluate(expression) { const s = expression; let i = 0; function skipSpaces() { while (i < s.length && s[i] === ' ') i++; } function isDigit(c) { return c >= '0' && c <= '9'; } function parsePrimary() { skipSpaces(); if (i >= s.length) { throw new Error('Unexpected end of input'); } const ch = s[i]; if (ch === '(') { i++; const value = parseAdd(); skipSpaces(); if (i >= s.length || s[i] !== ')') { throw new Error("Expected ')'"); } i++; return value; } if (isDigit(ch)) { return parseNumber(); } throw new Error('Unexpected token: ' + ch); } function parseNumber() { const start = i; while (i < s.length && isDigit(s[i])) i++; if (i < s.length && s[i] === '.') { i++; if (i >= s.length || !isDigit(s[i])) { throw new Error('Invalid number'); } while (i < s.length && isDigit(s[i])) i++; } return Number(s.slice(start, i)); } function parseUnary() { skipSpaces(); if (i < s.length && s[i] === '-') { i++; return -parseUnary(); } return parsePower(); } function parsePower() { const base = parsePrimary(); skipSpaces(); if (i < s.length && s[i] === '^') { i++; const exponent = parseUnary(); return base ** exponent; } return base; } function parseMul() { let left = parseUnary(); skipSpaces(); while (i < s.length && (s[i] === '*' || s[i] === '/')) { const op = s[i++]; const right = parseUnary(); if (op === '*') left *= right; else left /= right; skipSpaces(); } return left; } function parseAdd() { let left = parseMul(); skipSpaces(); while (i < s.length && (s[i] === '+' || s[i] === '-')) { const op = s[i++]; const right = parseMul(); if (op === '+') left += right; else left -= right; skipSpaces(); } return left; } skipSpaces(); const result = parseAdd(); skipSpaces(); if (i !== s.length) { throw new Error('Unexpected token: ' + s[i]); } return result; } ```563 tokens in, 10,967 out (10,346 of them reasoning) · 145.7 s · $0.0440 · 1 message on Pro · answered by deepseek/deepseek-v4-pro-0813 via Wafer ·
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] === ' ') i++; } function parseExpression() { let value = parseTerm(); while (true) { skip(); if (s[i] === '+') { i++; value += parseTerm(); } else if (s[i] === '-') { i++; value -= parseTerm(); } else { break; } } return value; } function parseTerm() { let value = parseUnary(); while (true) { skip(); if (s[i] === '*') { i++; value *= parseUnary(); } else if (s[i] === '/') { i++; value /= parseUnary(); } else { break; } } return value; } function parseUnary() { skip(); if (s[i] === '-') { i++; return -parseUnary(); } return parsePower(); } function parsePower() { const base = parsePrimary(); skip(); if (s[i] === '^') { i++; return base ** parseUnary(); } return base; } function parsePrimary() { skip(); if (s[i] === '(') { i++; const value = parseExpression(); skip(); if (s[i] !== ')') throw new Error('Invalid expression'); i++; return value; } return parseNumber(); } function parseNumber() { skip(); const start = 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++; 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 = parseExpression(); skip(); if (i !== s.length) throw new Error('Invalid expression'); return value; } ```1,786 tokens in, 9,267 out (8,654 of them reasoning) · 110.1 s · $0.0574 · 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”?
18 of 20 models passed this coding prompt's check (tests); Claude Haiku 4.5 and Mistral Large 4 didn't. The cheapest reply that passed was GLM 5.3 Flash's, at $0.00035; the fastest, Claude Haiku 5.5's in 3.9 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, GLM, and Mistral, 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.