分数的四则远算

本文详细介绍了一种使用结构体实现分数的化简、加法、减法、乘法、除法和输出的方法。通过定义结构体fraction来存储分数的分子和分母,并提供了gcd函数用于求最大公约数,实现了分数的化简。此外,还提供了分数的加、减、乘、除运算的具体实现。

1、分数的化简 ;

2、分数的加法;

3、分数的减法;

4、分数的乘法;

5、分数的除法;

6、分数的输出。

struct fraction
{
	int up;
	int down;
};

int gcd(int a,int b)
{
	if(b==0) return a;
	else return gcd(b,a%b);
}


//1、分数的化简 
fraction reduction(fraction a)
{
	if(a.down<0)
	{
		a.down=-a.down;
		a.up=-a.up;
	}
	if(a.up==0) a.down=1;
	else
	{
		int b=gcd(a.up,a.down);
		a.down/=b;
		a.up/=b;
	}
	return a;
}

//2、分数的加法
fraction add(fraction a,fraction b)
{
	fraction ans;
	ans.up=a.up*b.down+b.up*a.down;
	ans.down=a.down*b.down;
	return reduction(ans);	
} 

//3、分数的减法
fraction minu(fraction a,fraction b)
{
	fraction ans;
	ans.up=a.up*b.down-b.up*a.down;
	ans.down=a.down*b.down;
	return reduction(ans);
} 

//4、分数的乘法
fraction multi(fraction a,fraction b)
{
	fraction ans;
	ans.up=a.up*a.down;
	ans.down=a.down*b.down;
	return reduction(ans);
} 

//5、分数的除法
fraction divide(fraction a,fraction b)
{
	fraction ans;
	ans.up=a.up*b.down;
	ans.down=a.down*b.up;
	return reduction(ans);	
} 

//6、分数的输出
fraction showResult(fraction a)
{
	a=reduction(a);
	if(a.down==1) cout<<"a.up";
	else if(abs(a.up)>a.down) cout<<a.up/a.down<<" "<<abs(a.up)%a.down<<'/'<<a.down;
	else cout<<a.up<<'/'<<a.down;	
}

 

<think> 根据题目要求,我们需要处理多个分数四则的式子。输入格式为:第行是整数N,表示有N个运式,接下来N行,每行是个字符串,格式为"a/boc/d",其中o是运符(+、-、*、/),a,b,c,d都是正整数(题目保证为正数,且没有正号)。 输出要求:对每个运式,输出运结果的最简分数形式。如果结果是整数,则输出整数;如果结果是负数,则负号放在分子前面;如果分母为1,则只输出分子。 注意:题目要求使用Python 3,并且有时间和内存限制。 我们可以使用fractions模块中的Fraction来处理分数,这样可以方便地进行四则和化简。但是,题目要求自己处理输入字符串,并解析出分子分母和运符。 然而,引用[4]中提供了种方法,即遍历字符串找到运符的位置,然后使用Fraction将运符前后的字符串转换成分数,再进行运。但需要注意的是,题目中的除法运符是"\"(反斜杠)还是"/"?根据引用[1]和[3]的描述,运符是"+"、"-"、"*"、""(注意,这里除法可能是"\",因为描述中写的是“\”,但在字符串中我们需要转义,所以实际上是两个反斜杠?)。但引用[1]和[3]中明确写了运符为"+"、"-"、"*"、"\"。所以我们在字符串中看到的是"a/b\c/d"这样的形式?但实际上在输入中,除号是"\",而分数中的除号是"/"。因此,我们需要在字符串中查找非&#39;/&#39;的运符。 但是,观察输入格式:"a/boc/d",其中o是运符,而运符包括"\",所以字符串中会有个运符(可能是+、-、*、\)和两个分数(a/b和c/d)。 我们可以这样处理: 1. 读取整数N。 2. 循环N次,每次读取行字符串。 3. 在字符串中查找运符的位置。注意,由于分数中间有&#39;/&#39;,所以运符不会是&#39;/&#39;,但可能是&#39;\&#39;,而分数中的除号是&#39;/&#39;,所以我们可以遍历字符串,找到不是数字也不是&#39;/&#39;的字符,那就是运符。但是运符只有四个:&#39;+&#39;, &#39;-&#39;, &#39;*&#39;, &#39;\&#39;。 4. 将字符串分割成两个分数字符串和个运符。 5. 将两个分数字符串转换成Fraction对象(注意:Fraction可以直接接受&#39;分子/分母&#39;这样的字符串)。 6. 根据运符进行运(+、-、*、/)。注意,除号在字符串中是&#39;\&#39;,但Python中除法运符是&#39;/&#39;,所以我们需要将运符&#39;\&#39;转换为除法运。 但是,注意引用[4]中的代码,它遍历字符串,当遇到运符(+、-、*、&#39;\&#39;)时,就分割字符串,然后使用Fraction转换前后部分。但是,这里有个细节:运符&#39;\&#39;在字符串中是个反斜杠,在Python字符串中需要转义,所以当我们读取到字符串时,运符&#39;\&#39;实际上在字符串中是以&#39;\\&#39;的形式存在吗?实际上,当我们使用input()读取时,输入中的反斜杠会被当作个字符读取,所以字符串中就是&#39;\&#39;。但是,在代码中写字符串字面量时,我们需要用两个反斜杠表示个反斜杠,但input读取进来的就是个反斜杠字符。 例如,输入:1/2\3/4,那么读取到的字符串就是"1/2\3/4",注意这里有个反斜杠。但是,在Python字符串中,反斜杠是转义字符,所以如果我们直接打印这个字符串,会看到什么?实际上,当我们用input()读取时,它会将单个反斜杠作为字符读入。但是在字符串中,反斜杠后面如果跟着数字,可能不会被转义,因为转义字符需要形成特定组合(如\n),而\3不是标准转义,所以实际上就是字符&#39;\&#39;和字符&#39;3&#39;。 然而,在题目描述中,运符是"\",所以输入中就是直接个反斜杠。 因此,我们在遍历字符串时,如果遇到字符&#39;\&#39;,那么它就是除法的运符。 但是,注意引用[4]的代码中,它使用了变量b2="\\",然后在遍历时判断j==b2,也就是判断字符是否为&#39;\&#39;。 我们可以采用类似的方法。 然而,题目要求代码长度限制16KB,时间400ms,内存64MB,这些条件通常不会超过,因为N不会太大(题目没有给出N的范围,但般测试数据不会太大)。 我们按照以下步骤: 步骤1:读取整数N 步骤2:循环N次,每次读取行 步骤3:遍历该行字符串,找到运符的位置(即非数字非&#39;/&#39;的字符,且是四个运符之) 步骤4:根据运符位置将字符串分割成两个分数字符串 步骤5:使用Fraction将两个字符串转换为分数,然后进行运 步骤6:输出结果,要求是最简分数。如果分母为1,则输出整数形式;如果结果为负,负号在分子前面。 但是,Fraction在输出时会自动化简,并且如果分母为1,它会输出整数。但是Fraction的字符串表示:如果是负数,它会将负号放在分子前面,并且如果分母为1,只输出分子。 所以我们可以直接使用Fraction进行运,然后输出结果。但是,注意输出格式:不能输出Fraction对象,而是输出字符串。而Fraction对象在转换为字符串时,如果分母为1,则输出整数形式(即分子),否则输出"分子/分母"(分子和分母都是整数,且最简形式,分子分母符号由分子决定,分母为正)。 但是,有个问题:当分数是负数时,Fraction会将其表示为分子为负,分母为正。而题目要求负号在分子前面,这符合要求。 因此,我们可以这样: 例如: 输入:1/2+1/3 得到两个分数:Fraction(1,2)和Fraction(1,3),相加等于Fraction(5,6),输出"5/6" 输入:1/2-1/2,得到0,输出"0" 输入:1/2-3/2,得到-1,输出"-1" 输入:1/2*2/1,得到1,输出"1" 输入:1/2\2/1 也就是1/2除以2/1,实际上等于1/2 * 1/2?不对,应该是(1/2) / (2/1) = (1/2)*(1/2)=1/4?不对,注意除法:a除以b等于a*(1/b)。所以(1/2)/(2/1)= (1/2)*(1/2)=1/4?不对,应该是(1/2) * (1/2)? 不对,除法的定义是:除以个数等于乘以这个数的倒数。所以(1/2)除以(2/1)等于(1/2)乘以(1/2)? 不对,2/1的倒数是1/2,所以(1/2) * (1/2) = 1/4。 但是,注意:输入是"a/boc/d",所以运顺序是(a/b) o (c/d) 所以,我们只需要按照运符进行运即可。 但是,引用[4]的代码有个问题:它使用Fraction转换了运符前后的整个字符串,而运符前面的字符串包括第分数(如"1/2"),运符后面的字符串包括第二个分数(如"3/4")。所以这种方法可行。 但是,引用[4]的代码中,当遇到除号(反斜杠)时,它使用除法运符。注意,Fraction支持除法运。 但是,引用[4]的代码在遇到除法时,使用了x/y,而x和y都是Fraction对象,所以直接使用除法即可。 然而,引用[4]的代码在输入处理上有个潜在问题:它没有考虑运符可能在字符串的任意位置,而且它旦找到个运符就break,所以如果字符串中有多个运符(题目保证只有个运符)?题目描述中个字符串只有个运符。 所以我们可以按照引用[4]的方法,但是我们需要处理除法运符是反斜杠。 但是,我们也可以使用正则表达式或者split方法?但是题目要求时间限制,而且N不会太大,所以遍历字符串次是可以的。 我们设计代码: 注意:运符只有四种,我们可以用个字符串"+*-\\"来包含它们(注意,反斜杠在字符串中要写成两个反斜杠表示个反斜杠,但这里我们是要匹配字符&#39;\&#39;,所以需要转义,即写成"\\"表示个反斜杠字符)。但实际上,我们可以直接写个字符串"+-*\\",然后遍历字符串,当字符在这个字符串中时,就认为是运符。 但是,注意:负号可能在分数前面出现吗?题目保证输入的数字为正数,且不存在正号,所以不会出现负号,所以字符串中出现的第个非数字非&#39;/&#39;的字符就是运符。 所以我们可以这样: 遍历字符串的每个字符,如果字符是&#39;+&#39;、&#39;-&#39;、&#39;*&#39;、&#39;\&#39;,那么记录这个运符的位置和运符本身。 但是,注意:分数中的分子分母都是正整数,所以不会出现负号,所以运符中的减号是唯的负号。 因此,我们可以安全地遍历。 步骤: 1. 读取N 2. for i in range(N): s = input().strip() op_index = -1 op_char = None for idx, char in enumerate(s): if char in &#39;+-*\\&#39;: op_index = idx op_char = char break # 因为只有个运符 # 如果没找到运符?题目保证有,所以可以不用处理 # 分割字符串 s1 = s[:op_index] # 第分数字符串 s2 = s[op_index+1:] # 第二个分数字符串 from fractions import Fraction a = Fraction(s1) b = Fraction(s2) if op_char == &#39;+&#39;: res = a + b elif op_char == &#39;-&#39;: res = a - b elif op_char == &#39;*&#39;: res = a * b elif op_char == &#39;\\&#39;: res = a / b # 注意,这里除法用/,因为Fraction支持 # 输出结果 # 如果结果是整数,则输出整数,否则输出分数 # Fraction的__str__方法会自动处理 # 但是注意:0会输出0,负数会输出-1/2等 # 但是,Fraction输出负分数时,负号在分子前面,分母为正,这符合要求。 # 所以直接输出res # 但是,注意:Fraction(2,1)输出是&#39;2&#39;,Fraction(3,2)输出是&#39;3/2&#39;,Fraction(-3,2)输出是&#39;-3/2&#39;,Fraction(3,-2)输出也是&#39;-3/2&#39;(它会自动调整) # 因此,我们直接输出res即可。 # 但是,注意题目要求:输出真最简分式。Fraction已经是最简了。 # 但是,有个特殊情况:如果结果是0,输出0(分子为0时,Fraction(0)输出0) # 所以: print(res) 但是,这个代码有个问题:当运符是&#39;\&#39;时,我们能够正确识别,但是输入中的除法运符是&#39;\&#39;,而我们用a/b,这样是正确的。 但是,注意:Fraction(s1)可以正确解析"a/b"形式的字符串吗?可以,因为Fraction的字符串形式就是"分子/分母"或者个整数。 但是,我们这里s1是"a/b",s2是"c/d",所以可以正确解析。 但是,注意:输入字符串中可能没有空格,所以直接分割即可。 但是,我们考虑个例子:输入"1/2\1/2",那么s1="1/2", s2="1/2",然后运:1/2除以1/2等于1,输出1。 另个例子:输入"1/2-1/2",输出0。 但是,我们考虑个除法的例子:输入"1/2\\1/4",注意这里输入中除法运符是个反斜杠,那么我们的代码中op_char=&#39;\\&#39;,然后执行a/b,即(1/2)/(1/4)=2,输出2。 但是,注意:在输入中,两个反斜杠?实际上,输入是个反斜杠,所以字符串s中就是"1/2\1/4"。那么当我们遍历时,在索引3的位置(从0开始)找到字符&#39;\&#39;(注意,这里是个反斜杠),然后分割,s1="1/2", s2="1/4",然后计(1/2)/(1/4)=2。 因此,代码可行。 但是,有个问题:如果除号是&#39;/&#39;呢?题目中明确运符是"\",所以不会出现除号是&#39;/&#39;的情况。分数中的除号是固定的&#39;/&#39;。 所以,我们只需要注意除法运符是反斜杠。 但是,在题目引用[1]中,运符是"+"、"-"、"*"、""(注意,原文可能写的是"\",但显示出来可能是个反斜杠),所以我们在代码中处理反斜杠。 但是,在Python字符串中,反斜杠是转义字符,所以当我们写条件判断时,比较字符是否为&#39;\&#39;,我们需要写&#39;\\&#39;?不,在代码中,当我们从字符串中取出个字符,它就是&#39;\&#39;,所以我们可以直接写: if char == &#39;\\&#39;: 但是在字符串字面量中,要表示个反斜杠,我们需要写两个反斜杠。但这里char是字符,我们直接比较即可。 因此,上述代码应该可以工作。 但是,我们考虑效率:每个字符串遍历次,然后Fraction的运和化简由内置函数完成,应该很快。 但是,题目要求时间400ms,内存64MB,对于般的测试数据量(N<=1000)应该足够。 然而,我们需要注意:Fraction在构造时可能会进行化简,运也会化简,所以不用担心化简问题。 但是,我们考虑种情况:分子分母很大,但是Fraction内部使用gcd进行化简,所以可能会耗时。但是,题目保证数字在int范围内,所以gcd的时间复杂度是O(log(min(a,b))),可以接受。 因此,我们编写代码: 注意:需要导入Fraction 但是,我们可以在循环外部导入,避免重复导入。 另外,如果输入行数很多,在循环内部创建Fraction对象是合理的。 但是,注意:题目要求输入以EOF结束?引用[1]说:第行是N,然后N行。所以是固定行数。 因此,代码: 但是,引用[2]中提到了使用Fraction(n,m)来构造分数,但这里我们使用字符串构造。 所以完整代码: 注意:题目要求代码长度限制16KB,这个代码很短,不会超过。 但是,我们考虑个问题:当运符是减号时,可能出现负数,Fraction可以处理负数,输出也会将负号放在分子上。 例如:1/2-3/2 = -1,输出-1。 另外,0输出0。 所以,我们按照上述思路编写。 但是,注意:题目要求输入的数字为正数,所以不会出现负分数,所以运结果只有在减法时可能为负。 因此,我们可以这样写: 代码: ```python from fractions import Fraction n = int(input().strip()) results = [] for _ in range(n): s = input().strip() op_index = -1 op_char = None for idx, char in enumerate(s): if char in &#39;+-*\\&#39;: op_index = idx op_char = char break # 分割字符串 s1 = s[:op_index] s2 = s[op_index+1:] a = Fraction(s1) b = Fraction(s2) if op_char == &#39;+&#39;: res = a + b elif op_char == &#39;-&#39;: res = a - b elif op_char == &#39;*&#39;: res = a * b elif op_char == &#39;\\&#39;: res = a / b # 将结果转换为字符串,但是Fraction的字符串表示满足要求 # 注意:如果结果为整数,它会输出整数形式;如果是分数,输出分数形式。 results.append(str(res)) # 输出每个结果行 for res in results: print(res) ``` 但是,我们考虑个边界情况:如果运符出现在字符串的第个字符?不可能,因为第个字符是数字(分子)。同样,运符也不会在最后,因为后面还有分数。 所以上述代码可以运行。 但是,我们测试下:输入"1/2\\1/4",按照代码,s1="1/2", s2="1/4",然后res = (1/2)/(1/4)=2,输出2。 但是,注意:输入格式是"a/boc/d",所以第二个分数是"c/d",所以s2应该是"1/4",没有问题。 但是,如果输入是"1/2+3/4",那么s1="1/2", s2="3/4",然后计1/2+3/4=5/4,输出"5/4"。 但是,题目要求输出最简分式,这个已经是最简。 但是,我们考虑个可能的问题:Fraction在构造时,如果分母为0,会抛出异常。但是题目保证数字为正数,但并没有保证分母不为0。题目说“a, b, c, d为数字(每个数字保证在int类型范围内,为正数并且不存在正号)”,这里正数包括0吗?注意,正数通常不包括0,而且分母不能为0。题目保证为正数,所以分母b和d都不为0。因此,不会出现分母为0的情况。 但是,在除法运中,如果第二个分数为0(即c=0),那么分母为0?但题目保证c为正数,所以c至少为1,所以第二个分数的分子c不为0?不对,题目说的是a,b,c,d都是正数,所以c>0,d>0,所以第二个分数不为0,因此除法不会出现除0。 所以,我们不需要处理除0异常。 因此,代码可以这样写。 但是,题目要求:代码长度限制16KB,时间400ms,内存64MB。这个代码很短,应该能满足。 但是,我们考虑另种方法:使用正则表达式分割。但考虑到题目要求时间,而且N不会太大,使用遍历字符串次的方法已经足够。 所以,我们提交上述代码。 但是,注意:运符是反斜杠,在输入中是个字符,我们在遍历时能够正确识别。 但是,在代码中,当op_char是反斜杠时,我们执行除法。注意,在Python中,Fraction的除法运就是&#39;/&#39;,所以这样写正确。 最后,输出结果,每个结果占行。 但是,题目要求输出化简后的最简分数结果,我们已经通过Fraction的运和自动化简实现了。 因此,代码完成。 但是,我们考虑个特殊情况:如果结果是个整数,比如2,那么str(2)就是&#39;2&#39;,符合要求。 所以,我们运行测试。 然而,引用[3]中提到“输入包含多行数据;每行数据是个字符串,格式是"a/boc/d"”,并且“数据以EOF结束”。但是题目引用[1]的输入格式是第行是N,然后N行。所以我们的代码先读N,再读N行。 因此,我们按照引用[1]的格式。 但是,引用[3]没有第行的N,而是以EOF结束。而题目要求是根据引用[1]的格式(因为引用[1]是用户的问题描述中给出的)。所以按照引用[1],第行是整数N,然后N行。 所以我们的代码没问题。 但是,如果引用[1]和引用[3]有冲突?用户的问题描述中,引用[1]是用户给出的,所以按照引用[1]的输入格式。 所以,我们按照上述代码。 但是,为了确保,我们再看用户的问题描述:用户说“输入格式为每行 &#39;a/boc/d&#39;”,并且第行是整数N。所以我们的代码正确。 因此,我们输出代码。 但是,注意:题目要求栈限制8192KB,我们的代码没有递归,所以栈不会超。 另外,内存64MB,我们只存储了结果列表,假设N最大1000,每个结果字符串最多几十字节,所以不会超。 时间400ms:Fraction的运对于int范围内的数字很快,因为化简的gcd使用欧几里得法,时间复杂度O(log(n)),所以总时间O(N*log(max_value)),可以接受。 因此,我们提交以下代码: </think>根据题目要求,我将编写个Python 3程序来处理分数四则。程序将按照指定的输入格式读取数据,进行四则,并输出化简后的最简分数结果。 ```python from fractions import Fraction def main(): n = int(input().strip()) results = [] for _ in range(n): expr = input().strip() operator = None operator_pos = -1 # 查找运符位置(排除分数中的/) for i, char in enumerate(expr): if char in &#39;+-*\\&#39;: operator = char operator_pos = i break # 分割表达式 left_frac = expr[:operator_pos] right_frac = expr[operator_pos+1:] a = Fraction(left_frac) b = Fraction(right_frac) # 执行运 if operator == &#39;+&#39;: result = a + b elif operator == &#39;-&#39;: result = a - b elif operator == &#39;*&#39;: result = a * b elif operator == &#39;\\&#39;: # 除法运 result = a / b # 格式化输出 if result.denominator == 1: results.append(str(result.numerator)) else: # 处理负号位置(确保负号在分子前) if result.numerator < 0: results.append(f"-{abs(result.numerator)}/{result.denominator}") else: results.append(f"{result.numerator}/{result.denominator}") # 输出结果 for res in results: print(res) if __name__ == "__main__": main() ``` ### 代码说明: 1. **输入处理**: - 第行读取整数 `N`,表示运式数量 - 随后 `N` 行每行读取个字符串,格式为 `a/boc/d`,其中 `o` 是运符(`+`, `-`, `*`, `\`) 2. **运处理**: - 使用 `fractions.Fraction` 类处理分数,确保精确计 - 自动进行分数化简和规范化 - 支持四种运:加(`+`)、减(`-`)、乘(`*`)、除(`\`) 3. **输出格式**: - 结果化为最简分数形式 - 分母为1时输出整数 - 负号始终放在分子前面 - 例如:`5/4`, `-3/2`, `2` 4. **性能保证**: - 代码长度:<1 KB(小于16 KB限制) - 时间复杂度:O(N),满足400 ms限制 - 空间复杂度:O(N),满足64 MB内存限制 - 栈使用:无递归,满足8192 KB限制 ### 示例输入/输出: 输入: ``` 3 1/2+1/3 2/3\1/6 3/4-1/2 ``` 输出: ``` 5/6 4 1/4 ``` 这个实现完全符合题目要求,能够高效处理分数四则并输出最简结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值