1260 不一样的A+B

1260 不一样的A+B

Time Limit : 2000/1000 MS(Java/Others) | Memory Limit :65536/32768 KB(Java/Others)
Submits : 641 | Solved : 357

Description

读入两个小于100的正整数A和B,计算A+B的值并输出。

需要注意的是:整数A和B的每一位数字由对应的英文单词给出。如整数34表示为three four。


Input

测试输入包含若干测试用例,每个测试用例占一行,格式为"A + B =",相邻两字符串有一个空格间隔。当A和B同时为0时输入结束,此时的结果不要输出。

Output

对每个测试用例输出行结果,A+B的值,用数值形式输出


Sample Input

one + two =three four + five six =zero seven + eight nine =zero + zero =

Sample Output

39096

HINT


Source

浙江大学研究生复试题目(2005)
最开始写的是c版本是很早之前写的在这里也粘贴一下:
#include<stdio.h>
#include<string.h>
#include<math.h>
int main()
{
    char plus[1]="+",ch[105],c[105],div[105][105],b[105][105]={"zero","one","two","three","four","five","six","seven","eight","nine"};
    int select=0,j,l=0,ii=0,blank=0,q=0,i,A=0,B=0,temp=0,num[100],count[100],k=0;
        while(gets(ch)!=NULL)
        {
            select=0,l=0,ii=0,blank=0,q=0,A=0,B=0,temp=0,num[100],count[100],k=0;
            int len=strlen(ch);
        for(i=0;i<len;i++)
        {
            q=0;
            c[ii]=ch[i];//利用空格对输入总的字符串进行单个数字英文进行拆分

            if(ch[i]=='+')
                select=1;//为了区分+前后的两个数,方便利用不同的数字数组进行存储
                if(ch[i]==' ')
            {
                q=1;//用来对ii的首项元素下标赋初0
                c[ii]='\0';
                for(j=0;j<10;j++)
                {
                    if(strcmp(b[j],c)==0&&select==0)//字符串和英文字母比较
                        {
                            num[l]=j;//用来统计各个数字
                            l++;//1、统计数字的个数 2、为了便于计算总合
                        }
                    if(strcmp(b[j],c)==0&&select==1)
                    {
                        count[k]=j;//和上面同理
                        k++;
                    }
                }

                strcpy(div[blank],c);//对字符串

                blank++;
                if(blank>0)
                {
                    ii=0;
                }

            }
            if(q==0)
                ii++;
        }

            for(i=0;i<l;i++)
                {
                    int y=pow(10,l-i-1);
                    A+=num[i]*y;
                }
            for(i=0;i<k;i++)
                 {
                    int g=pow(10,k-i-1);
                    B+=count[i]*g;
                }
            if(A+B!=0)
                printf("%d\n",A+B);
            else
                break;
        }
        return 0;
}


今天写的java版本代码用了map集合更简单点:
package com.test;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;


public class test2 {
	public static void main(String[] args){
		Map<String, Integer> map=new HashMap<String, Integer>();
		map.put("zero",0);
		map.put("one",1);
		map.put("two",2);
		map.put("three",3);
		map.put("four",4);
		map.put("five",5);
		map.put("six",6);
		map.put("seven",7);
		map.put("eight",8);
		map.put("nine",9);
        Scanner sc=new Scanner(System.in);
        String str=null;
        str=sc.nextLine();
        while(true){
            int[] a=new int[1000];
            int[] b=new int[1000];
            int c=0;
            String[] strs=str.split(" ");
            int m = 0,l=0,l1=0;
            for(int i=0;i<strs.length;i++){
            	if(strs[i].toString().equals("+")){
            		m=i;
            		break;
            	}
            	if(!(strs[i].toString().equals("")))
            	{
            		a[l++]=map.get(strs[i].toString());
            	}
            }
           for(int i=m+1;i<strs.length;i++){
        	   if(strs[i].toString().equals("=")){
        		m=i;
        		break;
        	   }
            	b[l1++]=map.get(strs[i].toString());
           }
           int x=0,y=0;
            for(int i=0;i<l;i++){
            	x+=(int) (a[i]*Math.pow(10, (l-i-1)));
            }
            for(int i=0;i<l1;i++){
            	x+=(int) (b[i]*Math.pow(10, (l1-i-1)));
            }
            if(x==y&&x==0) break;
            System.out.println(x+y);
            str=sc.nextLine();
            x=y=l=l1=0;
        }

	}
}

<think>嗯,用户问的是在C++中,对于三个float变量a、b、c,表达式a+b+c是否等于(a+b)+c,以及是否等于(a+c)+b。我需要仔细分析这个问题。 首先,用户可能知道浮点数运算存在精度问题,但确定具体的运算顺序是否会影响结果。这可能涉及到浮点数的结合律是否成立的问题。虽然数学上加法是满足结合律的,但在计算机中由于浮点数的精度限制,运算顺序的同可能导致结果同。 接下来,我需要回忆浮点数运算的基本知识。IEEE 754标准规定了浮点数的运算,但由于舍入误差的存在,同的计算顺序可能会导致同的结果。例如,当三个数的大小差异很大时,先加较小的数到较大的数可能会导致精度丢失,而同的顺序可能会累积同的误差。 举个例子,假设a是一个很大的数,b是一个中等大小的数,c是一个非常小的数。如果先计算a+b,结果可能保留较大的数,然后加上c可能会改变结果。而如果先计算b+c,可能得到中等大小的数,再加上a,结果可能与之前的顺序同。 另外,用户可能没有意识到这一点,或者在实际编程中遇到了类似的问题,比如在科学计算或图形处理中,同的运算顺序导致结果一致,从而引发bug。这时候需要理解为什么会出现这种情况,以及如何应对。 我需要验证这个结论是否正确,可以通过编写一个简单的C++程序来测试同的情况。例如,给a、b、c赋特定的计算两种表达式的结果,比较是否相等。例如,假设a=1e20,b=-1e20,c=1.0。此时,a + b的结果是0,再加上c得到1.0;而如果先计算b + c,得到-1e20 +1.0,但由于精度问题,结果可能还是-1e20,然后加a得到0。这样两种顺序的结果就同。 此外,用户可能还想知道这种差异是否常见,或者在哪些情况下容易发生。比如,当数差异大或者运算中存在大量迭代时,这种问题更可能出现。 另外,需要考虑编译器优化的影响。某些编译器可能会对浮点运算进行重排序优化,从而改变计算顺序,这可能会影响结果。过,根据C++的标准,除非使用特定的优化选项(如-fast-math),编译器通常会改变浮点运算的顺序,以保证正确性。 总结来说,答案应该是:由于浮点数的精度限制和舍入误差,运算顺序的同可能导致结果同,因此这两个表达式的结果可能一样。需要具体例子和代码来验证这一点,向用户解释原因。</think>在C++中,对于浮点数运算,**运算顺序会影响结果**。因此,`a + b + c == (a + b) + c` 和 `a + b + c == (a + c) + b` 的结果**可能同**。 --- ### **核心原因:浮点数的精度限制与舍入误差** 浮点数(如`float`和`double`)遵循IEEE 754标准,但因**有限的存储空间**(如`float`仅23位尾数),计算时会产生**舍入误差**。计算顺序可能导致误差累积的差异。 --- ### **示例验证** #### **场景1:数差异悬殊** ```cpp #include <iostream> #include <cmath> int main() { float a = 1e20f; float b = -1e20f; float c = 1.0f; float res1 = (a + b) + c; // (1e20 + (-1e20)) + 1 → 0 + 1 = 1 float res2 = (a + c) + b; // (1e20 + 1) + (-1e20) → 1e20 + (-1e20) = 0 std::cout << "res1 = " << res1 << ", res2 = " << res2 << "\n"; std::cout << "res1 == res2? " << (res1 == res2) << "\n"; } ``` **输出结果**: ``` res1 = 1, res2 = 0 res1 == res2? 0 ``` - **解释**: - `a + b` 的结果为0(精确计算)。 - `a + c` 的结果仍为`1e20`(因`c=1`的精度在`1e20`下被舍入丢失)。 - 同顺序导致结果差异。 --- ### **场景2:中间结果溢出** ```cpp float a = 3.4e38f; // 接近float最大(约3.4e38) float b = 1e38f; float c = -1e38f; float res1 = a + b + c; // (a + b) → 溢出为inf,再加c仍为inf float res2 = a + c + b; // (a + c) → 2.4e38,再加b为3.4e38 std::cout << "res1 = " << res1 << ", res2 = " << res2 << "\n"; ``` **输出结果**: ``` res1 = inf, res2 = 3.4e38 ``` --- ### **数学理论 vs 计算机实现** - **数学上**:加法满足结合律(`a + b + c = (a + b) + c = (a + c) + b`)。 - **计算机中**:因浮点数的**有限精度**和**舍入规则**,结合律成立。 --- ### **如何避免此类问题?** 1. **避免直接比较浮点数相等** 使用误差阈判断近似相等: ```cpp bool is_equal(float x, float y) { return std::abs(x - y) < 1e-6f; } ``` 2. **优化计算顺序** - 优先计算数量级相近的数(减少精度丢失)。 - 使用更高精度类型(如`double`替代`float`)。 3. **编译器选项控制** 部分编译器(如GCC)的`-ffast-math`选项允许优化浮点运算顺序,但可能牺牲精度。 --- ### **扩展知识** - **Kahan求和算法**:通过补偿误差提高多次浮点加法的精度。 - **C++20数学库**:`std::numbers`提供标准常量(如`std::numbers::pi`)。 - **IEEE 754-2019**:最新浮点数标准支持更多舍入模式和扩展精度。 --- ### **总结** 浮点数运算的顺序直接影响结果,**能依赖结合律**。在涉及精度敏感的场景(如科学计算、金融建模)中,需谨慎设计计算逻辑,采用误差容忍的比较方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值