Skip to content

Commit d5b8211

Browse files
Fix Calculator Precision affecting Numeric evaluation (#338)
1 parent a43e027 commit d5b8211

File tree

2 files changed

+74
-2
lines changed

2 files changed

+74
-2
lines changed

src/strands_tools/calculator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,10 +378,10 @@ def numeric_evaluation(result: Any, precision: int, scientific: bool) -> Union[i
378378
# For floating point, evaluate numerically
379379
if isinstance(result, sp.Basic):
380380
if hasattr(result, "is_real") and result.is_real:
381-
float_result = float(result.evalf(precision)) # type: ignore
381+
float_result = float(result.evalf()) # type: ignore
382382
else:
383383
# Handle complex numbers
384-
complex_result = complex(result.evalf(precision)) # type: ignore
384+
complex_result = complex(result.evalf()) # type: ignore
385385
return format_number(complex_result, scientific, precision)
386386
else:
387387
float_result = float(result)

tests/test_calculator_precision.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
"""
2+
Regression tests for calculator precision handling.
3+
4+
Precision must affect ONLY formatting, not numeric value.
5+
"""
6+
7+
from strands_tools.calculator import calculator
8+
9+
10+
def extract_text(result):
11+
assert result["status"] == "success"
12+
return result["content"][0]["text"]
13+
14+
15+
# ------------------------------------------------------------
16+
# Core regression tests (original bug)
17+
# ------------------------------------------------------------
18+
19+
def test_precision_does_not_change_real_value():
20+
r2 = calculator("221 * 318.11", precision=2)
21+
r4 = calculator("221 * 318.11", precision=4)
22+
23+
t2 = extract_text(r2)
24+
t4 = extract_text(r4)
25+
26+
assert "70302.31" in t2
27+
assert "70302.31" in t4 # trailing zeros are stripped by design
28+
29+
30+
def test_precision_does_not_change_division_value():
31+
r2 = calculator("10 / 3", precision=2)
32+
r6 = calculator("10 / 3", precision=6)
33+
34+
t2 = extract_text(r2)
35+
t6 = extract_text(r6)
36+
37+
assert "3.33" in t2
38+
assert "3.333333" in t6
39+
40+
41+
# ------------------------------------------------------------
42+
# Complex number regression tests
43+
# ------------------------------------------------------------
44+
45+
def test_precision_does_not_change_complex_value():
46+
r2 = calculator("(1 + I) * 318.11", precision=2)
47+
r4 = calculator("(1 + I) * 318.11", precision=4)
48+
49+
t2 = extract_text(r2)
50+
t4 = extract_text(r4)
51+
52+
assert "318.11" in t2
53+
assert "318.11" in t4
54+
55+
56+
# ------------------------------------------------------------
57+
# Symbolic guardrails (correct semantics)
58+
# ------------------------------------------------------------
59+
60+
def test_expression_with_symbols_remains_symbolic():
61+
r = calculator("x + 1", precision=2)
62+
t = extract_text(r)
63+
64+
assert "x + 1" in t
65+
66+
67+
def test_force_numeric_applies_numeric_evaluation():
68+
r = calculator("sqrt(2)", precision=4, force_numeric=True)
69+
t = extract_text(r)
70+
71+
assert "1.4142" in t
72+

0 commit comments

Comments
 (0)