gaussian-rational
gaussian-rational provides an exact, immutable complex-like scalar where both
components are rational numbers (fractions.Fraction).
Use GaussianRational when you want complex arithmetic without intermediate
floating-point rounding in the real and imaginary parts.
Highlights
- Exact real and imaginary components (
Fraction-backed). - Immutable value type, safe to share across threads.
- Complex-style arithmetic (
+,-,*,/, integer**). - Compatible real equality/hash behavior for purely real values.
- Flexible string parsing and formatting.
- Fully typed (PEP 561, inline annotations).
Installation
pip install gaussian-rational
Quick Start
from fractions import Fraction
from gaussian_rational import GaussianRational
z = GaussianRational(Fraction(1, 3), Fraction(2, 5))
w = GaussianRational(2, -1)
print(z + w) # 7/3-3j/5
print(z * w) # 16/15+7j/15
print(z / w) # 4/15+j/3
print(z.conjugate()) # 1/3-2j/5
print(z.real, z.imag) # Fraction(1, 3) Fraction(2, 5)
print(complex(z)) # (0.3333333333333333+0.4j)
print(z.arg()) # atan2(float(imag), float(real))
Construction
GaussianRational normalizes several input forms:
from fractions import Fraction
from gaussian_rational import GaussianRational
GaussianRational(3, 4) # a=3, b=4
GaussianRational((Fraction(1, 2), Fraction(2))) # tuple input
GaussianRational(5) # purely real, imag=0
GaussianRational(GaussianRational(1, 2)) # identity/upcast
GaussianRational("1/2+2j") # string parse
Accepted component types are int and Fraction.
API Summary
Numeric operations
+,-, unary-*,/- Integer exponentiation
**nforn: int abs(x)returnsfloatcomplex(x)returns built-incomplexusingfloatcasts of both parts
Properties and helpers
real,imag— rational components, mirroringcomplexconjugate()— complex conjugatea - biarg()— phase angle in radians (atan2(imag, real))as_tuple()— explicit(real, imag)tupleabs_squared()— exact norm-squared asFraction- Predicates:
is_real,is_imaginary,is_zero_or_imaginary,is_composite,is_zero - Parsing:
GaussianRational.parse(...) - Formatting:
format(...),str(...),repr(...)
If you want deterministic ordering, sort explicitly with as_tuple():
sorted_values = sorted(values, key=lambda z: z.as_tuple())
String Formatting
GaussianRational provides three string surfaces:
| Surface | Description |
|---|---|
str(z) |
Calls z.format(). |
z.format(...) |
Configurable exact symbolic output. |
format(z, spec) / f-strings |
Empty spec → symbolic; non-empty spec → float-based complex semantics. |
repr(z) |
Eval-safe constructor form, for example GaussianRational(Fraction(1, 2), 3). |
Formatting rules:
- Real-only values print as rational scalars (for example
3,-1/2). - Imaginary-only values print with
jattached (for examplej,-2j,j/3,-5j/7). - Composite values print as
a+bjora-bjwith no spaces. force_sign=Trueadds a leading+for non-negative outputs.parens_if_composite=Truewraps composite outputs in parentheses; for non-composite values, rational fractions are parenthesized instead.imag_charoverrides the symbol per call (for exampleimag_char="i").GaussianRational.default_imag_charsets the class-wide default.- For
format(z, spec): non-emptyspecusescomplexformatting semantics, mapping the imaginary symbol to the class default.
Examples:
from fractions import Fraction
from gaussian_rational import GaussianRational
str(GaussianRational(3, 0)) # "3"
str(GaussianRational(0, 1)) # "j"
str(GaussianRational(1, -2)) # "1-2j"
GaussianRational(1, 2).format(force_sign=True) # "+1+2j"
GaussianRational(Fraction(1, 2), Fraction(1, 3)).format(
parens_if_composite=True,
) # "(1/2+j/3)"
GaussianRational(1, 2).format(imag_char="i") # "1+2i"
repr(GaussianRational(Fraction(1, 2), Fraction(-3, 4))) # "GaussianRational(Fraction(1, 2), Fraction(-3, 4))"
f"{GaussianRational(Fraction(1, 2), Fraction(-5, 3)):.2f}" # "0.50-1.67j"
repr(z) is an eval-safe round-trip given from fractions import Fraction and
from gaussian_rational import GaussianRational in scope.
Parsing String Literals
GaussianRational.parse parses symbolic literals and is also used by
GaussianRational("...").
from fractions import Fraction
from gaussian_rational import GaussianRational
GaussianRational.parse("1+2j") # GaussianRational(1, 2)
GaussianRational.parse("(2/3)j") # GaussianRational(0, Fraction(2, 3))
GaussianRational.parse("2j/3") # GaussianRational(0, Fraction(2, 3))
GaussianRational.parse(" 1/2 + 3 i ", imag_char=("i", "j"))
GaussianRational.parse("2/3j", interpret_slash_j_as_j_slash=True)
Parsing notes:
- Embedded spaces are ignored.
imag_characcepts a single character or a tuple of aliases.- By default, ambiguous
2/3jis rejected; setinterpret_slash_j_as_j_slash=Trueto accept it as2j/3. GaussianRationalLikeintentionally excludesstr, so arithmetic dunder upcasting never treats arbitrary strings as numeric.
Examples
Conjugate product gives exact norm-squared
from fractions import Fraction
from gaussian_rational import GaussianRational
z = GaussianRational(Fraction(3, 4), Fraction(-5, 6))
prod = z * z.conjugate()
print(prod) # 181/144
print(prod.is_real) # True
print(prod.real) # Fraction(181, 144)
print(z.abs_squared()) # Fraction(181, 144)
Division remains exact
from fractions import Fraction
from gaussian_rational import GaussianRational
x = GaussianRational(Fraction(1, 2), Fraction(1, 3))
y = GaussianRational(Fraction(2, 5), Fraction(-1, 7))
q = x / y
print(q.real) # Fraction(1295, 1222)
print(q.imag) # Fraction(980, 1833)
Integer powers
from gaussian_rational import GaussianRational
z = GaussianRational(1, 1)
print(z ** 2) # 2j
print(z ** -1) # 1/2-j/2
Interop with built-in complex
from fractions import Fraction
from gaussian_rational import GaussianRational
z = GaussianRational(Fraction(1, 3), Fraction(5, 2))
c = complex(z)
print(c) # (0.3333333333333333+2.5j)
print(type(c)) # <class 'complex'>
Semantics and Compatibility
GaussianRational is designed to feel close to complex while preserving
exact rational components.
- Truthiness matches numeric convention: only
GaussianRational(0, 0)is false. - Equality accepts
GaussianRational,int, andFractionvalues. - Equality intentionally does not accept tuples:
GaussianRational(1, 2) == (1, 2)isFalse. - Hashing is aligned for purely real values so equality and hash stay consistent with compatible real scalars.
- Instances are immutable and safe to share across threads.
Current intentional limitation:
- Exponentiation supports integer powers only.
Type Hints
This package ships inline type hints and a py.typed marker (PEP 561).
Public typing aliases:
FractionLike = Fraction | intGaussianRationalLike = GaussianRational | tuple[FractionLike, FractionLike] | FractionLike
Advanced Usage
Subclassing
GaussianRational is immutable and uses __slots__ for compact instances.
Subclassing is supported with a few rules:
- Do not assign attributes normally (
self.x = ...) after construction; useobject.__setattr__in__new__instead. - If your subclass adds fields, declare its own
__slots__. - Keep
type(self)(a, b)compatible with your subclass constructor, since arithmetic results are constructed that way.
Minimal pattern:
from gaussian_rational import GaussianRational
class TaggedGaussianRational(GaussianRational):
__slots__ = ("tag",)
def __new__(cls, v, v2=None, *, tag: str = ""):
self = super().__new__(cls, v, v2)
object.__setattr__(self, "tag", tag)
return self
Subclass contract for repr round-trips:
__repr__ is implemented as f"{type(self).__name__}({self.format()!r})".
A subclass that adds state beyond the real and imag slots must override both format()
(to encode that state in the string) and parse() (to decode it), so that
eval(repr(z)) remains a valid round-trip.
Common pitfalls:
- Forgetting
__slots__on the subclass, which reintroduces__dict__. - Changing constructor semantics so
type(self)(a, b)no longer works. - Adding mutable fields while keeping hashing enabled (invalidates hash contract if mutable fields affect equality).
Supported Python Versions
Python 3.10 and later.
License
MIT. See LICENSE.
For development and release workflow documentation, see CONTRIBUTING.md.
Metadata
Release files for gaussian-rational 1.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| gaussian_rational-1.0.2.tar.gz | 17.2 kB | With provenance | Details for gaussian_rational-1.0.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| gaussian_rational-1.0.2-py3-none-any.whl | Python 3 | none | any | Details for gaussian_rational-1.0.2-py3-none-any.whl |
Total release size: 31.0 kB
Release files / gaussian_rational-1.0.2.tar.gz
| Download URL | gaussian_rational-1.0.2.tar.gz |
|---|---|
| Size | 17.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
872247ea5e76c12e7d3941fb41f70fcec1b9fcabd400340cce741b757911f373
|
|
BLAKE2b-256 checksum How to use checksums |
570cb21b72d8e6d9c9a66ad06237e36bde8c3b26a4c43ad32a97ef4044a6b3e8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 24, 2026.
Transparency logRelease files / gaussian_rational-1.0.2-py3-none-any.whl
| Download URL | gaussian_rational-1.0.2-py3-none-any.whl |
|---|---|
| Size | 13.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
466c99d27835fd269f0060f62dc47591466f5f77d15ca5569f216fd631519b0a
|
|
BLAKE2b-256 checksum How to use checksums |
a890893ec7687e3f747c3d5dc98162ca446db33f80094a8ad8ed052c0ae299d8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 24, 2026.
Transparency logSecurity for gaussian-rational 1.0.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for gaussian_rational-1.0.2.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 24, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.