feat(fstring): implement scientific and percentage formatting
This commit is contained in:
@@ -1,33 +1,48 @@
|
|||||||
// Basic type
|
print("Basic type")
|
||||||
let a = 42
|
let a = 42
|
||||||
print(f"int: {a:d}; hex: {a:x}; HEX: {a:X}; oct: {a:o}; bin: {a:b}")
|
print(f"int: {a:d}; hex: {a:x}; HEX: {a:X}; oct: {a:o}; bin: {a:b}")
|
||||||
|
print()
|
||||||
|
|
||||||
// Grouping
|
print("Grouping")
|
||||||
let b = 1234567890
|
let b = 1234567890
|
||||||
print(f"{b:,}")
|
print(f"{b:,}")
|
||||||
print(f"{b:_}")
|
print(f"{b:_}")
|
||||||
|
print()
|
||||||
|
|
||||||
let c = 1234.5678
|
let c = 1234.5678
|
||||||
print(f"{c:,._}")
|
print(f"{c:,._}")
|
||||||
print(f"{c:_.,}")
|
print(f"{c:_.,}")
|
||||||
|
print()
|
||||||
|
|
||||||
// Sign
|
print("Sign")
|
||||||
let d1 = 14
|
let d1 = 14
|
||||||
let d2 = -26
|
let d2 = -26
|
||||||
print(f"{d1} {d2}")
|
print(f"{d1} {d2}")
|
||||||
print(f"{d1:+} {d2:+}")
|
print(f"{d1:+} {d2:+}")
|
||||||
print(f"{d1:-} {d2:-}")
|
print(f"{d1:-} {d2:-}")
|
||||||
print(f"{d1: } {d2: }")
|
print(f"{d1: } {d2: }")
|
||||||
|
print()
|
||||||
|
|
||||||
// Percentage
|
print("Percentage")
|
||||||
let pts = 19
|
let pts = 19
|
||||||
let total = 22
|
let total = 22
|
||||||
print(f"Correct answers: {pts/total:.2%}")
|
print(f"Correct answers: {pts/total:.2%}")
|
||||||
|
print()
|
||||||
|
|
||||||
// Precision
|
print("Precision")
|
||||||
print(f"{c:8}")
|
print(f"{c:8}")
|
||||||
print(f"{c:8.2}")
|
print(f"{c:8.2}")
|
||||||
print(f"{c:.2}")
|
print(f"{c:.2}")
|
||||||
print(f"{c:.8}")
|
print(f"{c:.8}")
|
||||||
|
print()
|
||||||
|
|
||||||
// Complex
|
print("Scientific")
|
||||||
|
print(f"{a:e}")
|
||||||
|
print(f"{b:e}")
|
||||||
|
print(f"{c:e}")
|
||||||
|
print(f"{d1:e}")
|
||||||
|
print(f"{d2:e}")
|
||||||
|
print(f"{0:e}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("Complex")
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from math import log10, floor
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
from src.core.format_spec.spec import FormatSpec
|
from src.core.format_spec.spec import FormatSpec
|
||||||
@@ -75,8 +76,12 @@ class StringFormatter:
|
|||||||
res = obj
|
res = obj
|
||||||
case TokenType.T_BIN | TokenType.T_DEC | TokenType.T_HEX | TokenType.T_HEX_CAPS | TokenType.T_OCT:
|
case TokenType.T_BIN | TokenType.T_DEC | TokenType.T_HEX | TokenType.T_HEX_CAPS | TokenType.T_OCT:
|
||||||
res = self.format_int(obj, spec, fmt_type)
|
res = self.format_int(obj, spec, fmt_type)
|
||||||
case TokenType.T_SCI | TokenType.T_FIX | TokenType.T_PCT:
|
case TokenType.T_FIX:
|
||||||
res = self.format_float(obj, spec, fmt_type)
|
res = self.format_float_fix(obj, spec, fmt_type)
|
||||||
|
case TokenType.T_PCT:
|
||||||
|
res = self.format_float_fix(obj * 100, spec, TokenType.T_FIX) + "%"
|
||||||
|
case TokenType.T_SCI:
|
||||||
|
res = self.format_float_sci(obj, spec, fmt_type)
|
||||||
|
|
||||||
if spec.number.integral.width is not None:
|
if spec.number.integral.width is not None:
|
||||||
res = self.pad(res, spec.number.integral.width)
|
res = self.pad(res, spec.number.integral.width)
|
||||||
@@ -92,7 +97,7 @@ class StringFormatter:
|
|||||||
|
|
||||||
return sign + string
|
return sign + string
|
||||||
|
|
||||||
def format_float(self, value: float, spec: FormatSpec, fmt_type: TokenType) -> str:
|
def format_float_fix(self, value: float, spec: FormatSpec, fmt_type: TokenType) -> str:
|
||||||
sign: str = self.make_sign(value, spec)
|
sign: str = self.make_sign(value, spec)
|
||||||
value = abs(value)
|
value = abs(value)
|
||||||
integer: int = int(value)
|
integer: int = int(value)
|
||||||
@@ -100,9 +105,16 @@ class StringFormatter:
|
|||||||
integer_spec = spec.number.integral
|
integer_spec = spec.number.integral
|
||||||
decimal_spec = spec.number.decimal
|
decimal_spec = spec.number.decimal
|
||||||
|
|
||||||
|
precision: Optional[int] = None
|
||||||
|
if fmt_type == TokenType.T_SCI:
|
||||||
|
precision = 6
|
||||||
|
|
||||||
if decimal_spec is not None:
|
if decimal_spec is not None:
|
||||||
if decimal_spec.precision is not None:
|
if decimal_spec.precision is not None:
|
||||||
decimal = round(decimal, decimal_spec.precision)
|
precision = decimal_spec.precision
|
||||||
|
|
||||||
|
if precision is not None:
|
||||||
|
decimal = round(decimal, precision)
|
||||||
|
|
||||||
integer_str: str = self.format_int_part(integer, fmt_type, integer_spec.grouping)
|
integer_str: str = self.format_int_part(integer, fmt_type, integer_spec.grouping)
|
||||||
decimal_str: str = self.format_int_part(int(str(decimal)[2:]), fmt_type, None if decimal_spec is None else decimal_spec.grouping)
|
decimal_str: str = self.format_int_part(int(str(decimal)[2:]), fmt_type, None if decimal_spec is None else decimal_spec.grouping)
|
||||||
@@ -111,6 +123,14 @@ class StringFormatter:
|
|||||||
|
|
||||||
return f"{sign}{integer_str}{decimal_str}"
|
return f"{sign}{integer_str}{decimal_str}"
|
||||||
|
|
||||||
|
def format_float_sci(self, value: float, spec: FormatSpec, fmt_type: TokenType) -> str:
|
||||||
|
sign: str = self.make_sign(value, spec)
|
||||||
|
value = abs(value)
|
||||||
|
mag: int = 0 if value == 0 else floor(log10(value))
|
||||||
|
coef: float = value / (10 ** mag)
|
||||||
|
coef_str: str = self.format_float_fix(coef, spec, fmt_type)
|
||||||
|
return f"{sign}{coef_str}e{mag:+03d}"
|
||||||
|
|
||||||
def format_int_part(self, value: int, fmt_type: TokenType, grouping: Optional[Token]):
|
def format_int_part(self, value: int, fmt_type: TokenType, grouping: Optional[Token]):
|
||||||
groups: int = 4
|
groups: int = 4
|
||||||
string: str = str(value)
|
string: str = str(value)
|
||||||
|
|||||||
Reference in New Issue
Block a user