呵呵,好像我来这里这么久了都没有用分的机会,现在来散一下
早前在这个区和.NET Framework区看到两次这个题目了,都没看到有人给出能处理极端情况的答案,所以再来提一次。已知:
int a, b;
并已赋值,值的唯一限制是int.MinValue<=a,b<=int.MaxValue,所有极端情况均有可能
例如 a = 2147483647, b = 2147000000
又或 a = -2147483600, b = -2147483640
又或 a = 2000000000, b = -2000000000
当然也包括 a = 0, b = 0 (-_-)现在要将a,b的值交换没有任何导入的命名空间(即如果你要用类,必须从System开始写起)
没有任何辅助的方法(即如果你要辅助方法,你要自己写)
除了a和b没有其它已经声明的字段或参数或局部变量,并且不能再声明任何变量!求最短的、编译可以通过的、所有情况下都能达到目的的 C# 代码我已知的最短的代码是 ## 字节,看能不能打破这个纪录(##: 为激起挑战欲,我不便公开,反正是个某些国家看来不吉利的数字)2天之内结用来测试的代码:
class Program
{
static void Main()
{
int a = 1234567890, b = 987654321;
/**************************\
* 将你的答案填入下面两个斜杠内 *
*//*
* 将你的答案填入上面两个斜杠内 *
\**************************/
System.Console.WriteLine("a={0},b={1}", a, b);
System.Console.ReadLine();
}
}给分标准:
1)一旦出现少于##个字节的正确答案,100分全给;
2)两天之内没有达到(1)的话,等于##字节的第一个正确答案100分;
3)没有达到(2)的话,根据回复所体现的钻研精神和创意分配100分祝大家斗得开心,玩得愉快 ^o^提示:嗯,提示已经出现在本贴里!
早前在这个区和.NET Framework区看到两次这个题目了,都没看到有人给出能处理极端情况的答案,所以再来提一次。已知:
int a, b;
并已赋值,值的唯一限制是int.MinValue<=a,b<=int.MaxValue,所有极端情况均有可能
例如 a = 2147483647, b = 2147000000
又或 a = -2147483600, b = -2147483640
又或 a = 2000000000, b = -2000000000
当然也包括 a = 0, b = 0 (-_-)现在要将a,b的值交换没有任何导入的命名空间(即如果你要用类,必须从System开始写起)
没有任何辅助的方法(即如果你要辅助方法,你要自己写)
除了a和b没有其它已经声明的字段或参数或局部变量,并且不能再声明任何变量!求最短的、编译可以通过的、所有情况下都能达到目的的 C# 代码我已知的最短的代码是 ## 字节,看能不能打破这个纪录(##: 为激起挑战欲,我不便公开,反正是个某些国家看来不吉利的数字)2天之内结用来测试的代码:
class Program
{
static void Main()
{
int a = 1234567890, b = 987654321;
/**************************\
* 将你的答案填入下面两个斜杠内 *
*//*
* 将你的答案填入上面两个斜杠内 *
\**************************/
System.Console.WriteLine("a={0},b={1}", a, b);
System.Console.ReadLine();
}
}给分标准:
1)一旦出现少于##个字节的正确答案,100分全给;
2)两天之内没有达到(1)的话,等于##字节的第一个正确答案100分;
3)没有达到(2)的话,根据回复所体现的钻研精神和创意分配100分祝大家斗得开心,玩得愉快 ^o^提示:嗯,提示已经出现在本贴里!
解决方案 »
- TextBox 数据绑定 修改数据后要移动到其他行才能保存
- 使用PANEL加载窗体效果问题
- 线程中调用控件
- C#中改变窗口标题
- ComponentOne Studio 中有人知道如何用C1ReportDesigner 合并某列的相同行吗
- C#导出Excel 出现问题
- 简单的C#去系统日期的问题
- (C#.net)在内存中生成的缩略图,如何把该缩略图赋给image控件来显示?
- !!如何把datatable中的数据更新到DB中!!
- Silverlight 报表打印参数设置怎么弄
- TabControl问题填充DataGrid问题,请救!
- 有谁知道 Head First Design Patterns(深入浅出设计模式) 中文版的电子书下载地址 阿
b = 2;a = a + b;
b = a - b;
a = a - b;搂主给分吧。
肯定是它,但问题是他是13位,也就是现在还没要破的记录!看谁能少于13位吧
a-=b-=a+=b;
// a^=b^(b^=a^b);
Response.Write("a="+a+"<br>");
Response.Write("b="+b+"<br>");
测试通过
int a = 1234567890, b = 987654321;
失败 没考虑周全 又菜鸟了一回 唉
用^反复试 都是太长
也就是说b = a + ( a = b ) * 0会先算右边的a + ( a = b ) * 0。加法运算符的优先级别比赋值运算高,并且运算顺序是从左至右。
所以a + ( a = b ) * 0会先计算左边的a,然后再计算( a = b ) * 0,就是这个顺序使得a的值可以暂存。
剩下的事情就是把a=b这个表达式的值给消掉了,方法也很简单,两个字节搞定,*0。
当(a=b)的时候
b=a+(a=b)*0第一个a是1吗?为什么?
b=a+(a=b)-a
b=a+(a=b)-b
上面两个结果一样,效率是否是下面那两个高点?
b=a+(a=b)-a
b=a+(a=b)-b
b=a+(a=b)-b
溢出
不知道有分没有?int a = 2147483647;
int b = -2147483640;
a=b|a&~(b=a);
像微软,google样的公司,因为他们一天到晚都在想法考试自己,以为这样智力就高了,
从sb的王小丫,再到sb的忘了那个叫什么了,反正呵呵...
b^=a^=b;a^=b;注意:要使它能够编译,分号也是必须的,所以上面11个字节、12个字节的答案,其实是12字节、13字节,不过 Ivony 的12字节的答案:
b=a+(a=b)*0;
完全符合要求,所以根据我原来设定的给分方法,Ivony获100---------------------------其实我顺便还想找的东西是最小化CPU用量,传统方法:c=a;a=b;b=c 用了3次提取,3次赋值;
异或方法:b^=a^=b;a^=b 用了4次提取,3次运算,3次赋值,虽然省掉了一个变量,但是比较浪费性能
而Ivony的方法却只有2次提取,2次运算,2次赋值
我记得的是赋值操作比运算慢,所以我猜2/2/2跟3/0/3大概是同一个级别的yuanarea(Sail before)的方法 a=b|a&~(b=a); 也比全异或少了1次提取1次赋值,所以也很值得我崇拜,不过你的语句13字符长,被Ivony打下去了XD
这个答案不仅仅是代码最短的,也是效率最高的,因为C#的编译器非常之聪明给它做了优化,便以出了下列IL,从IL的角度来说,都是最简表达了,没有比他更短、更简洁的IL。
IL_000c: ldloc.0//第一个变量压栈,即把a压栈。
IL_000d: ldloc.1//第二个变量压栈,即把b压栈。
IL_000e: stloc.0//出栈赋值给第一个变量,即把栈顶的值弹出并付给a(因为栈是先进先出的,所以这个值是b的值)
IL_000f: stloc.1//出栈赋值给第二个变量,即把栈顶的值弹出并付给b。
其实根本没有运算,就压栈两次出栈两次,应该不会有比这更快的了。
你可以好好研究下为什么了`~~!petshop4() ( ) 信誉:100 2006-7-24 13:39:54 得分: 0
b=a+(a=b)-a
b=a+(a=b)-b
溢出
b=a+(a=b)-a =》b=(a+(a=b))-a
当10亿+20亿等于多少?
INT最大不过2147483647
不要以为结果没错就不是溢出
b = 2;a = a + b;
b = a - b;
a = a - b;搂主给分吧。
但是这样的语法解析让我感觉到恐惧,
b=a+(a=b)*0;
这样的语句执行过程在 c/cpp 中如下
(为了说明,old_a或old_b代表 a或b的原值。)
a=b ==> a = old_b;
(a=b)规约后令其为 R1, 其值为old_b;同时a的值也是 old_b
R1*0规约后令其为R2 值为0
a+R2 ==> old_b + R2 规约后令其为R3 ,其值为 old_b
b=R3 规约后令其为 R4,其值为 old_b ,同时 b的值也是old_b
所以,在c/cpp中
b=a+(a=b)*0; 地执行结果是 b和a都是old_b。
而不是 swap;在c/cpp中,下面的例子应该是写法最简的(在devcpp中运行通过)。#include <cstdlib>
#include <iostream>using namespace std;int main(int argc, char *argv[])
{
int a ,b;
a= 5; b = 6;
printf("\n %d ,%d ",a,b);
b^=a^=b^=a;
printf("\n %d ,%d ",a,b);
system("PAUSE");
return EXIT_SUCCESS;
}效率最高的做法如果涉及内存变量的交换的话可能是如WYlslrt(WY.lslrt) 所说。
用xchg示意代码如下。mov ax,a
xchg ax,b
mov a,ax但也不一定,具体还要看厂家的实现的该指令的指令周期。如果不涉及内存变量,而是两个寄存器变量的话,那么b^=a^=b^=a; 绝对是最快的。
在寄存器间的操作和在内存中的操作决定不是一个等级的。
而且那种做法优点还在于不借助其他寄存器或变量。是目前历史上最优的做法。
虽然没有用过.net,但Ivony() 的解释中,明显的也用了第三方变量,而且用了两个,
呵呵,两次的压栈,和申明两个变量无疑。也就是说需要至少两次进出栈的,
也就是说汇编指令应该如下push a,
push b,
pop b,
pop a,
作了4次访存操作.........
b=(a,a=b)
没想到调试不成功,难道C#已经把“,”运算符去掉了?
现在的公司都要求TeamWork的,这样的代码,你让别人怎么改,谁敢改。
特别是日本企业,这样的代码,肯定要被指摘的。
如果本来就是计算机天才的话,研究一下这个还是支持的。
如果不是Coding狂人的话,有时间去研究一下OOP可能更有意义!
但这种行为是被严格定义的,可以在C# 语言规范 1.2版,第7.2章节中找到:表达式中的操作数从左到右进行计算。例如,在 F(i) + G(i++) * H(i) 中,F 方法是使用 i 的旧值调用的,然后 G 方法也是使用 i 的旧值进行调用,最后 H 方法使用 i 的新值调用。这与运算符的优先级无关。尽管写这么BT的代码并不是推荐的,但这条语法规范确实能帮我们省掉一些代码,如典型的:
while( str != ( str = str.Replace(" ", " " ) );这在C++中也是有可能得不到预期的结果的。
不知道为什么,C#下可以正确,但.net的C++下b=a+(a=b)*0; 的结果就成了 b=2,a=2本来受启发想到可以这样
b=(a,a=b)
没想到调试不成功,难道C#已经把“,”运算符去掉了?因为()的优先级最高(a=b)时a已经等于2了,因此最后就成了b=2+0;
所以C#这个语法优先级挺奇怪,一般都是()优先级最高。
因此一开始我还以为Ivony()的b=a+(a=b)*0这句话最后执行结果是a和b都等于2。
应该还考虑硬件性能,这种题只有指定了CPU种类和程序平台被才有实际价值,
一旦被编译器优化,自己的代码写成啥样都一样.
而且字节短有什么用,效率高才是重要的,若是没有乘法指令集的CPU(比如6502),*0反而会慢
b = a + (a = b) * 0; 实际执行的机器指令只有
00000015 mov ebx,dword ptr [edi]
00000017 mov eax,dword ptr [esi]
00000019 mov dword ptr [edi],eax
0000001b mov dword ptr [esi],ebx
MS的编译器优化技术都出神入化了.
楼上有同志说()优先级最大,固然没错,但是单独的一个变量,比如a,也是一个表达式;在表达式“a+(b+c)”,不应该先计算(),应该先计算a的值(虽然实际上只是取个变量而已),