diff --git a/.spec/math/fraction_spec.lua b/.spec/math/fraction_spec.lua index e67fba1..469de74 100644 --- a/.spec/math/fraction_spec.lua +++ b/.spec/math/fraction_spec.lua @@ -13,6 +13,10 @@ describe("Fraction", function() { base = 2, str = "0.(10)", val = frac(2, 3) }, { base = nil, str = "3.(3)", val = frac(10, 3) }, -- test default base { base = 10, str = "1.2(3)", val = frac(12, 10) + frac(1, 30) }, + { base = 10, str = "1", val = frac(1, 1) }, + { base = 10, str = "-2", val = frac(-2, 1) }, + { base = 10, str = "-1.25", val = frac(-5, 4) }, + { base = 10, str = "-1.3(51)", val = frac(-223, 165) }, { base = 16, str = "1.(45d17)", val = frac(42, 33) }, } diff --git a/src/math/fraction.lua b/src/math/fraction.lua index 88311fb..2eeafce 100644 --- a/src/math/fraction.lua +++ b/src/math/fraction.lua @@ -70,8 +70,8 @@ local function read_base_param(base) return base end -function fraction.from_float_string( - str, -- {}.{digit}[({digit})], ex.: `-1.2(3)` +local function parse_positive_double_string( + str, -- EBNF: digit { digit } "." { digit } [ "(" digit { digit } ")" ], ex.: `1.2(3)` base -- integer from 2 to 36, defaults to 10 (decimal) ) base = read_base_param(base) @@ -81,6 +81,7 @@ function fraction.from_float_string( local integer, fractional = str:match("^([0-9a-zA-Z][0-9a-zA-Z]-)%.([0-9a-zA-Z%(%)]+)") if not fractional then + assert(str:match("[0-9a-zA-Z]+")) return new(read_number(str), 1) end @@ -96,6 +97,16 @@ function fraction.from_float_string( return read_number(integer) + after_dot / base ^ #pre_period end +function fraction.from_float_string( + str, -- EBNF: [ "-" ] digit { digit } "." { digit } [ "(" digit { digit } ")" ], ex.: `-1.2(3)` + base -- integer from 2 to 36, defaults to 10 (decimal) +) + if str:sub(1, 1) == "-" then + return -parse_positive_double_string(str:sub(2), base) + end + return parse_positive_double_string(str, base) +end + -- Conversions function metatable:__tostring()