Given two strings s
and t
, each of which represents a non-negative rational number, return true
if and only if they represent the same number. The strings may use parentheses to denote the repeating part of the rational number. A rational number can be represented using up to three parts: <IntegerPart>
, <NonRepeatingPart>
, and a <RepeatingPart>
. The number will be represented in one of the following three ways:
<IntegerPart>
12
, 0
, and 123
.<IntegerPart>.<NonRepeatingPart>
0.5
, 1.
, 2.12
, and 123.0001
.<IntegerPart>.<NonRepeatingPart>(<RepeatingPart>)
0.1(6)
, 1.(9)
, 123.00(1212)
.The repeating portion of a decimal expansion is conventionally denoted within a pair of round brackets. For example: 1/6 = 0.16666666... = 0.1(6) = 0.1666(6) = 0.166(66)
. Can you implement a function to determine if two given rational numbers represented as strings are equal? Here are a few examples:
s = "0.(52)", t = "0.5(25)"
should return true
s = "0.1666(6)", t = "0.166(66)"
should return true
s = "0.9(9)", t = "1."
should return true
The problem asks us to determine if two strings, s
and t
, representing rational numbers (possibly with repeating decimal parts), are equal. The strings can have an integer part, a non-repeating decimal part, and a repeating decimal part enclosed in parentheses.
A straightforward but potentially problematic approach involves converting both strings into floating-point numbers (doubles) and then comparing them. However, this can lead to issues due to the limitations of floating-point precision, especially when dealing with infinitely repeating decimals.
Issues with the Naive Approach:
The most reliable way to compare rational numbers with repeating decimals is to convert them into fractions (numerator/denominator). Then, we can compare the fractions by reducing them to their simplest form and checking if the numerators and denominators match.
Here's the outline of the algorithm:
s
and t
.IntegerPart.NonRepeatingPart(RepeatingPart)
I
be the IntegerPart, N
be NonRepeatingPart, and R
be RepeatingPart.Example: Converting "0.1(6)" to a fraction:
Edge Cases:
import math
def string_to_fraction(s):
if '.' not in s:
integer_part = int(s)
return integer_part, 1
integer_part, decimal_part = s.split('.')
integer_part = int(integer_part) if integer_part else 0
if '(' not in decimal_part:
if not decimal_part:
numerator = integer_part
denominator = 1
else:
numerator = int(integer_part * (10**len(decimal_part)) + int(decimal_part))
denominator = 10**len(decimal_part)
return numerator, denominator
non_repeating, repeating_part = decimal_part.split('(')
repeating = repeating_part[:-1]
num = integer_part
den = 1
if non_repeating:
num = num * (10**len(non_repeating)) + int(non_repeating)
den = 10**len(non_repeating)
if repeating:
repeating_num = int(repeating)
repeating_den = 10**len(repeating) - 1
num = num * repeating_den + repeating_num
den = den * repeating_den
return num, den * (10**len(non_repeating) if non_repeating else 1)
def gcd(a, b):
if b == 0:
return a
return gcd(b, a % b)
def isRationalEqual(s, t):
num1, den1 = string_to_fraction(s)
num2, den2 = string_to_fraction(t)
gcd1 = gcd(num1, den1)
num1 //= gcd1
den1 //= gcd1
gcd2 = gcd(num2, den2)
num2 //= gcd2
den2 //= gcd2
return num1 == num2 and den1 == den2
# Example Usage:
s1 = "0.(52)"
s2 = "0.5(25)"
print(f"{s1} == {s2}: {isRationalEqual(s1, s2)}")
s3 = "0.9(9)"
s4 = "1."
print(f"{s3} == {s4}: {isRationalEqual(s3, s4)}")
s5 = "0.1666(6)"
s6 = "0.166(66)"
print(f"{s5} == {s6}: {isRationalEqual(s5, s6)}")
string_to_fraction(s)
: This function parses the input string s
and converts it into a fraction (numerator, denominator).gcd(a, b)
: This function calculates the greatest common divisor (GCD) of two numbers using the Euclidean algorithm.isRationalEqual(s, t)
: This function converts both strings into fractions, simplifies the fractions by dividing by their GCD, and then compares the simplified numerators and denominators.