added mudolor and is even is odd
This commit is contained in:
parent
7e67c3fcf9
commit
8699d8f7ab
@ -13,7 +13,17 @@ pip install -e .
|
||||
Create digit files anywhere you like (the examples below use `instance/log`), then construct `StreamNumber` objects, and call the helpers:
|
||||
|
||||
```python
|
||||
from mathstream import StreamNumber, add, sub, mul, div, pow
|
||||
from mathstream import (
|
||||
StreamNumber,
|
||||
add,
|
||||
sub,
|
||||
mul,
|
||||
div,
|
||||
mod,
|
||||
pow,
|
||||
is_even,
|
||||
is_odd,
|
||||
)
|
||||
|
||||
a = StreamNumber("instance/log/huge.txt")
|
||||
b = StreamNumber("instance/log/tiny.txt")
|
||||
@ -23,7 +33,10 @@ print("sum =", "".join(add(a, b).stream()))
|
||||
print("difference =", "".join(sub(a, b).stream()))
|
||||
print("product =", "".join(mul(a, b).stream()))
|
||||
print("quotient =", "".join(div(a, b).stream()))
|
||||
print("modulo =", "".join(mod(a, b).stream()))
|
||||
print("power =", "".join(pow(a, e).stream()))
|
||||
print("a is even?", is_even(a))
|
||||
print("b is odd?", is_odd(b))
|
||||
```
|
||||
|
||||
Each arithmetic call writes its result back into `instance/log` (configurable via `mathstream.number.LOG_DIR`) so you can stream the digits later or reuse them in further operations.
|
||||
@ -33,15 +46,16 @@ Each arithmetic call writes its result back into `instance/log` (configurable vi
|
||||
- **StreamNumber(path)** – Wraps a digit text file. The file may include an optional leading sign (`+` or `-`). Whitespace is ignored; digits must otherwise be contiguous.
|
||||
- **`.stream(chunk_size)`** – Yields strings of digits with the provided chunk size. Operations in `mathstream.engine` consume these streams to avoid loading the entire number at once.
|
||||
- **Automatic staging** – Outputs are stored under `LOG_DIR` with hashes based on input file paths, letting you compose operations without manual bookkeeping.
|
||||
- **Sign-aware** – Addition, subtraction, multiplication, division (`//` behavior), and exponentiation (non-negative exponents) all respect operand sign. Division follows Python’s floor division rules.
|
||||
- **Sign-aware** – Addition, subtraction, multiplication, division (`//` behavior), modulo, and exponentiation (non-negative exponents) all respect operand sign. Division/modulo follow Python’s floor-division rules.
|
||||
- **Utilities** – `clear_logs()` wipes prior staged results so you can start fresh.
|
||||
- **Parity helpers** – `is_even` and `is_odd` inspect the streamed digits without materializing the integer.
|
||||
|
||||
## Example Script
|
||||
|
||||
`test.py` in the repository root demonstrates a minimal workflow:
|
||||
|
||||
1. Writes sample operands to `tests/*.txt`.
|
||||
2. Calls every arithmetic primitive.
|
||||
2. Calls every arithmetic primitive plus the modulo/parity helpers.
|
||||
3. Asserts that the streamed outputs match known values (helpful for quick regression checks).
|
||||
|
||||
Run it via:
|
||||
|
||||
@ -1,2 +1,11 @@
|
||||
from .engine import clear_logs, add, sub, mul, div, pow
|
||||
from .engine import clear_logs, add, sub, mul, div, mod, pow, is_even, is_odd
|
||||
from .number import StreamNumber
|
||||
|
||||
__all__ = [
|
||||
"clear_logs",
|
||||
"add", "sub",
|
||||
"mul", "div", "mod",
|
||||
"pow",
|
||||
"is_even", "is_odd",
|
||||
"StreamNumber",
|
||||
]
|
||||
|
||||
@ -261,6 +261,26 @@ def div(num_a: StreamNumber, num_b: StreamNumber) -> StreamNumber:
|
||||
return _write_result("div", (num_a, num_b), result)
|
||||
|
||||
|
||||
def mod(num_a: StreamNumber, num_b: StreamNumber) -> StreamNumber:
|
||||
"""Return num_a % num_b following Python's floor-division semantics."""
|
||||
sign_a, a_digits = _normalize_stream(num_a)
|
||||
sign_b, b_digits = _normalize_stream(num_b)
|
||||
|
||||
_, remainder = _divide_abs(a_digits, b_digits)
|
||||
|
||||
if remainder == "0":
|
||||
return _write_result("mod", (num_a, num_b), "0")
|
||||
|
||||
if sign_a == sign_b:
|
||||
digits = remainder
|
||||
else:
|
||||
digits = _sub_abs(b_digits, remainder)
|
||||
|
||||
sign = 1 if sign_b > 0 else -1
|
||||
result = digits if sign > 0 else f"-{digits}"
|
||||
return _write_result("mod", (num_a, num_b), result)
|
||||
|
||||
|
||||
def pow(num_a: StreamNumber, num_b: StreamNumber) -> StreamNumber:
|
||||
"""Return num_a ** num_b using repeated squaring (integer exponent only)."""
|
||||
base_sign, base_digits = _normalize_stream(num_a)
|
||||
@ -289,3 +309,14 @@ def pow(num_a: StreamNumber, num_b: StreamNumber) -> StreamNumber:
|
||||
result_sign = 1
|
||||
result = result_digits if result_sign > 0 else f"-{result_digits}"
|
||||
return _write_result("pow", (num_a, num_b), result)
|
||||
|
||||
|
||||
def is_even(num: StreamNumber) -> bool:
|
||||
"""Return True if the streamed integer is even."""
|
||||
_, digits = _normalize_stream(num)
|
||||
return (ord(digits[-1]) - 48) % 2 == 0
|
||||
|
||||
|
||||
def is_odd(num: StreamNumber) -> bool:
|
||||
"""Return True if the streamed integer is odd."""
|
||||
return not is_even(num)
|
||||
|
||||
31
test.py
31
test.py
@ -2,7 +2,18 @@ from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from mathstream import StreamNumber, add, sub, mul, div, pow, clear_logs
|
||||
from mathstream import (
|
||||
StreamNumber,
|
||||
add,
|
||||
sub,
|
||||
mul,
|
||||
div,
|
||||
mod,
|
||||
pow,
|
||||
is_even,
|
||||
is_odd,
|
||||
clear_logs,
|
||||
)
|
||||
|
||||
NUMBERS_DIR = Path(__file__).parent / "tests"
|
||||
|
||||
@ -27,6 +38,11 @@ def check(label: str, result: StreamNumber, expected: str) -> None:
|
||||
print(f"{label} = {actual}")
|
||||
|
||||
|
||||
def check_bool(label: str, value: bool, expected: bool) -> None:
|
||||
assert value is expected, f"{label} expected {expected}, got {value}"
|
||||
print(f"{label} = {value}")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
clear_logs()
|
||||
|
||||
@ -35,6 +51,7 @@ def main() -> None:
|
||||
small = write_number("tiny", "34567")
|
||||
negative = write_number("negative", "-1200")
|
||||
exponent = write_number("power", "5")
|
||||
negative_divisor = write_number("neg_divisor", "-34567")
|
||||
|
||||
# Showcase the core operations.
|
||||
total = add(big, small)
|
||||
@ -42,6 +59,10 @@ def main() -> None:
|
||||
product = mul(small, negative)
|
||||
quotient = div(big, small)
|
||||
powered = pow(small, exponent)
|
||||
modulus = mod(big, small)
|
||||
neg_mod_pos = mod(negative, small)
|
||||
pos_mod_neg = mod(small, negative)
|
||||
neg_mod_neg = mod(negative, negative_divisor)
|
||||
|
||||
print("Operands stored under:", NUMBERS_DIR)
|
||||
check("huge + tiny", total, "98765432123491356")
|
||||
@ -49,6 +70,14 @@ def main() -> None:
|
||||
check("tiny * negative", product, "-41480400")
|
||||
check("huge // tiny", quotient, "2857217349595")
|
||||
check("tiny ** power", powered, "49352419431622775997607")
|
||||
check("huge % tiny", modulus, "6424")
|
||||
check("negative % tiny", neg_mod_pos, "33367")
|
||||
check("tiny % negative", pos_mod_neg, "-233")
|
||||
check("negative % neg_divisor", neg_mod_neg, "-1200")
|
||||
check_bool("is_even(negative)", is_even(negative), True)
|
||||
check_bool("is_even(tiny)", is_even(small), False)
|
||||
check_bool("is_odd(tiny)", is_odd(small), True)
|
||||
check_bool("is_odd(negative)", is_odd(negative), False)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
1
tests/neg_divisor.txt
Normal file
1
tests/neg_divisor.txt
Normal file
@ -0,0 +1 @@
|
||||
-34567
|
||||
Loading…
x
Reference in New Issue
Block a user