【基础练习】n&1==0错在哪儿?

本文源自一道关于质因数分解的编程题目,在讨论如何通过位运算判断数字奇偶性时发现了一个常见误区:位运算符&的优先级较低。文章通过实际案例解释了这一现象,并强调了使用括号来提高代码可读性和正确性的必要性。

这个问题源于一道分解质因数的水题(codevs 1313)

我的源码中有一段是

int n,p;
	scanf("%d",&n);
	if (n&1==0){
		printf("%d",n/2);
		return 0;
	}
可是问题出现了 如果我们输入一个偶数 这个程序块根本不跑

这是一项很奇怪的事 因为快速幂非递归中 我们常用到if(n&1==1)这样的句子

LGA大婶,ZLC神犇纷纷表示无法解答 但鄙人在知乎上找到了答案http://www.zhihu.com/question/20798455

因为这时候我才恍然大悟:位运算优先级非常低 左右移甚至比加减运算优先级还低

没想到的原因 一个是P党时代不用考虑这个 直接and shr这样的 在一个是平时也不大注意 果然还是加括号吧 也能提高程序可读性

——明明如月,何时可掇?忧从中来,不可断绝。



#include <math.h> #include<stdio.h> #include<stdlib.h> #include<time.h> void menu(void); int do_singleadd(); int do_singlesub(); int do_singlemul(); int do_singlediv(); int do_singlemixed(); void do_add(); void do_sub(); void do_mul(); void do_div(); void do_mixed(); int main() { srand(time(0)); int choice; while(1) { menu(); printf("请选择:"); scanf("%d",&choice); if(choice==0) { printf("期待下次运算,再见~"); break; } switch(choice) { case 1:do_add();break; case 2:do_sub();break; case 3:do_mul();break; case 4:do_div();break; case 5:do_mixed();break; default:printf("不符合要求,请重试!!!"); } printf("\n&quot;); } return 0; } void menu() { printf("\n=====~四则运算练习系统~=====\n&quot;); printf("1.加法运算\n&quot;); printf("2.减法运算\n&quot;); printf("3.乘法运算\n&quot;); printf("4.除法运算\n&quot;); printf("5.混合运算\n&quot;); printf("0.退出系统\n&quot;); printf("\n============================\n&quot;); } void circulate_count(int type) { int total=5; int right_count=0; int score=0; float total_time=0; const char*type_name[]={"加法","减法","乘法","除法","混合运算"}; printf("\n======%s练习=====\n&quot;,type_name[type-1]); printf("将进行5道题目,请做好准备!\n&quot;); for(int i=1;i<=total;i++) { printf("\n第%d题",i); time_t start_time=time(NULL); int flag=0; switch(type) { case 1:flag = do_singleadd();break; case 2:flag = do_singlesub();break;; case 3:flag = do_singlemul();break; case 4:flag = do_singlediv();break; case 5:flag = do_singlemixed();break; } time_t end_time=time(NULL); int time_used=(int)difftime(end_time, start_time); total_time += time_used; if(flag==1) { right_count++; score+=20; } printf("用时: %d秒\n&quot;,time_used); } float average_time=total_time/total; printf("\n练习结束!成绩单:\n&quot;); printf("答对题目:%d\n&quot;,right_count); printf("正确率:%.2f\n&quot;,((float)right_count/total)*100); printf("最终得分:%d\n&quot;,score); printf("平均每题用时:%.1f秒\n&quot;,average_time); if (score==100) { printf("太棒了!!!"); } else if (score>=80 && score<=100) { printf("很不啦!"); } else if (score>=60 && score<=80) { printf("还有提升空间~"); } else { printf("需要更多练习哦!\n&quot;); } } int do_singleadd() { int a=rand()%20+1; int b=rand()%20+1; int ans; int attempts=3; int is_correct=0; while(attempts>0){ printf("\n %d+%d=?(还有%d次机会)",a,b,attempts); scanf("%d",&ans); if(ans==a+b) { printf("Very good!"); is_correct=1; break; } else { attempts--; if(attempts>0) printf("Wrong!再试一次!\n&quot;); } } if(!is_correct) printf("\n正确答案是:%d\n&quot;, a+b); return 0; } void do_add(){ circulate_count(1);//现在是加法模式 } int do_singlesub() { int a=rand()%20+1; int b=rand()%20+1; int ans; int attempts=3; int is_correct=0; while(attempts>0){ printf("\n %d-%d=?(还有%d次机会)",a,b,attempts); scanf("%d",&ans); if(ans==a-b) { printf("Very good!"); is_correct=1; break; } else { attempts--; if(attempts>0) printf("Wrong!再试一次!\n&quot;); } } if(!is_correct) printf("\n正确答案是:%d\n&quot;, a-b); return 0; } void do_sub() { circulate_count(2); } int do_singlemul() { int a=rand()%20+1; int b=rand()%20+1; int ans; int attempts=3; int is_correct=0; while(attempts>0){ printf("\n %d*%d=?(还有%d次机会)",a,b,attempts); scanf("%d",&ans); if(ans==a*b) { printf("Very good!"); is_correct=1; break; } else { attempts--; if(attempts>0) printf("Wrong!再试一次!\n&quot;); } } if(!is_correct) printf("\n正确答案是:%d\n&quot;, a*b); return 0; } void do_mul() { circulate_count(3); } int do_singlediv() { int result=rand()%9+2; int b=rand()%10+1; int a=b*result; int ans; int attempts=3; int is_correct=0; while(attempts>0){ printf("\n %d/%d=?(还有%d次机会)",a,b,attempts); scanf("%d",&ans); if(ans==a/b) { printf("Very good!"); is_correct=1; break; } else { attempts--; if(attempts>0) printf("Wrong!再试一次!\n&quot;); } } if(!is_correct) printf("\n正确答案是:%d\n&quot;, a/b); return 0; } void do_div() { circulate_count(4); } int do_singlemixed() { char ops[]={'+','-','*','/'}; int a=rand()%20+1; int b=rand()%20+1; int c=rand()%20+1; char op1=ops[rand()%4]; char op2=ops[rand()%4]; float correct=0; if ( (op1=='+'||op1=='-')&& (op2=='*'||op2=='/')) { float second=(op2=='*')?b*c:(float)b/c; correct =(op1 =='+')?a+second:a-second; } else { float first; switch(op1) { case '+': first = a + b; break; case '-': first = a - b; break; case '*': first = a * b; break; case '/': first = (float)a / b; break; } switch(op2) { case '+': correct = first + c; break; case '-': correct = first - c; break; case '*': correct = first * c; break; case '/': correct = first / c; break; } } float ans; printf("%d %c %d %c %d=?",a,op1,b,op2,c); printf("\n(结果保留两位小数)"); scanf("%f",&ans); if(fabs(ans-correct)<0.01) { printf("Very good!"); return 1; } else { printf("Wrong!"); return 0; } } void do_mixed() { circulate_count(5); } 在这个基础上压缩一下更加简洁,并且希望混合运算也能给出三次运算机会
最新发布
11-16
<think>好的,我现在需要帮助用户理解累加和累乘赋初值的区别。用户之前问过如何用sum实现阶乘,现在这个问题是关于赋初值的,看起来是初学者的常见问题。 首先,用户可能刚开始学习编程,对变量初始化不太清楚。他们可能知道sum通常用来累加,但不太明白为什么累乘的初始值要设为1,而sum是0。需要解释清楚初始值的选择对结果的影响。 接下来,我得考虑用户的实际应用场景。他们可能在写循环结构时遇到了问题,比如结果总是不对,可能因为初始值设了。比如累乘如果初始值为0,结果就会一直是0,导致误。需要举例说明不同初始值的结果差异,这样用户能直观理解。 用户可能没有明确说出,但深层需求是理解为什么不同的运算需要不同的初始值,以及如何正确使用它们。需要分点讲解,用简单易懂的例子,比如累加和累乘的具体步骤,说明初始值的重要性。 还要注意对比累加和累乘的不同,强调初始值的选择与运算的恒等元素有关,比如加法的恒等元素是0,乘法的恒等元素是1。这样用户能理解背后的数学原理,而不仅仅是记住规则。 可能需要用代码示例来展示正确和误的初始化情况,让用户看到不同的结果。例如,累乘初始值设为0时,每次循环相乘结果都是0,这样用户就能明白误所在。 最后,总结两者的区别和注意事项,帮助用户记忆。可能还要提醒用户在实际编程中常见的误,比如忘记初始化或者选初始值,导致程序出,这样他们能避免类似的误。</think>好的!理解累加(Sum)和累乘(Product)的初始值设定是编程中的关键基础。以下是清晰的对比和解释: --- ### **核心概念** - **累加**:将一系列数字**相加**,初始值为 **`0`**(因为 `0` 是加法的“单位元”,不影响结果)。 - **累乘**:将一系列数字**相乘**,初始值为 **`1`**(因为 `1` 是乘法的“单位元”,不影响结果)。 --- ### **1. 累加(sum)的初值为什么0?** #### **原理** - 数学中,加法从 `0` 开始累积: $$0 + a_1 + a_2 + \dots + a_n$$ - 若初始值不为 `0`,结果会多出额外值(例如初值为 `1` 时,总和会多 `1`)。 #### **代码示例** ```python # 正确:sum 初始值 0 sum_result = 0 for num in [2, 3, 5]: sum_result += num print(sum_result) # 输出 10(正确:0+2+3+5) # 误:sum 初始值 1 sum_error = 1 for num in [2, 3, 5]: sum_error += num print(sum_error) # 输出 11误:1+2+3+5) ``` --- ### **2. 累乘(product)的初值为什么1?** #### **原理** - 数学中,乘法从 `1` 开始累积: $$1 \times a_1 \times a_2 \times \dots \times a_n$$ - 若初始值不为 `1`: - 初值为 `0` 时,结果永远为 `0`(任何数乘 `0` 都是 `0`)。 - 初值为其他数(如 `2`),结果会被额外放大。 #### **代码示例** ```python # 正确:product 初始值 1 product = 1 for num in [2, 3, 5]: product *= num print(product) # 输出 30(正确:1×2×3×5) # 误:product 初始值 0 product_error = 0 for num in [2, 3, 5]: product_error *= num print(product_error) # 输出 0误:0×2×3×5) ``` --- ### **对比表格** | **操作** | 初始值 | 数学意义 | 误初始值示例 | 误结果原因 | |----------|--------|-------------------------|---------------------|-----------------------| | 累加 | `0` | $0 + a_1 + a_2 + \dots$ | 初值为 `1` | 总和多出初始值 | | 累乘 | `1` | $1 \times a_1 \times a_2 \times \dots$ | 初值为 `0` | 结果被强制归零 | --- ### **常见误场景** 1. **忘记初始化**: ```python sum_result = 0 # 必须显式赋初值! for num in data: sum_result += num ``` 2. **混淆初始值**: ```python # 误:计算乘积时初始值为0 product = 0 # ❌ 应该为1 for num in [2, 4, 5]: product *= num # 结果永远是0 ``` --- ### **记忆口诀** - **“加零乘一”**: 累加从 `0` 开始(零起点),累乘从 `1` 开始(一起乘)。 --- ### **练习题目** 尝试补全以下代码: 1. 计算列表 `[3, 5, 7]` 的累加和: ```python sum_val = ___ # 初始值 for x in [3, 5, 7]: sum_val ___ x print(sum_val) # 应输出15 ``` 2. 计算列表 `[2, 4, 6]` 的累乘积: ```python product = ___ # 初始值 for y in [2, 4, 6]: product ___ y print(product) # 应输出48 ``` 答案: 1. `sum_val = 0`,`+=` 2. `product = 1`,`*=` 如果还有其他疑问,欢迎随时提问! 😊
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值