java语言题目,以下选项中正确的java表达式
这篇文章给大家带来了一些关于java的知识,包括一些关于语言表达式的相关问题,包括奇数,变,长整数等。下面就来看看吧,希望对你有帮助。
如何解决写爬虫IP受阻的问题?立即使用。
谜题一:奇数性
以下方法旨在确定其唯一参数是否为奇数。这种方法能正确工作吗?
公共静态布尔isOdd(int i){
returni%2==1:
}奇数可以定义为整数除以2,余数为1。表达式i%2计算的是I除以2产生的余数,所以看起来这个程序应该工作正常。可惜不能;它有四分之一的时间会返回错误的答案。
为什么是四分之一?因为所有int值有一半是负数,而isOdd方法将无法判断所有负奇数。对任何负整数调用此方法都会返回false,而不管该整数是偶数还是奇数。这是Java定义余数运算符(%)的结果。该运算符被定义为对于所有int值A和所有非零int值B满足以下等式:
(a/b)*b (a%b)==a
换句话说,如果你把A除以B,把商乘以B,然后加上余数,那么你就得到了原来的值A,这个恒等式有正确的意义,但是和Java的截断整数整除运算符结合起来,就意味着当余数运算返回非零结果时,它和左操作数具有相同的正负符号。
当I为负奇数时,i%2等于-1而不是1,所以isOdd方法会错误返回false。为了防止这种事故,请测试您的方法在为每个数值参数传递负值、零和正值时是否行为正确。这个问题好改。只需将i%2与0而不是1进行比较,并颠倒比较的含义:
公共静态布尔isOdd(inti){
returni%2!=0;
}如果在性能关键的环境中使用isOdd方法,最好用位操作符和()替换余数操作符:
公共静态布尔isOdd(inti){
return(i1)!=0;
}总之,无论何时使用余数运算符,都要考虑操作数和结果的符号。当操作数为非负时,该运算符的行为很明显,但当一个或两个操作数都为负时,其行为就不那么明显了。
走吧。
当前位置请考虑下面文章中描述的问题:
汤姆在一家汽车配件商店买了一个价值1.10美元的火花塞,但他的钱包里装满了两美元的钞票。如果他用一张两美元的钞票买这个火花塞,他应该得到多少零钱?
下面是一个试图解决上述问题的程序。它会打印什么?
公共类别更改{
公共静态void main(String args[]){
systemoutprintln(2.00-1.10);
}
}你可能天真地期待程序打印0.90,但它怎么知道你要打印小数点后两位呢?
如果你对DoubletoString文档中设置的将双类型值转换为字符串的规则有所了解,你就会知道这个程序打印的十进制数是最短的十进制数,足以将双类型值与其最近的邻居区分开。小数点前后至少有一位数字。因此,程序应该打印0.9似乎是合理的。
这种分析看似合理,其实并不正确。如果运行该程序,您会发现它会打印:
0.8999999999999999
问题是数字1.1无法准确表示为double,所以表示为与其最接近的double值。这是程序从2中减去的值。不幸的是,这个计算的结果并不是最接近0.9的double值。结果的double值的最短表示就是你看到打印出来的那个可恶的数字。
更普遍的问题是,不是所有的小数都可以用二进制浮点数精确表示。
如果您使用的是JDK5.0或更高版本,那么您可能会尝试使用printf工具来设置输出精度,从而更正程序:
//糟糕的解决方案-仍然使用二进制浮点数
System.out.printf(%.2f%n ,2.00-1.10);该语句打印出正确的结果,但并不意味着它是底层问题的通用解决方案:它使用了double运算,这仍然是一个二进制浮点数。浮点运算在大范围的值中提供了很好的近似值,但它通常不能产生准确的结果。二进制浮点非常不适合货币计算,因为不可能将0.1——或者10的任何其他次负幂——精确地表示为长度有限的二进制小数。解决这个问题的一种方法是使用某种整数类型,如int或long,并以除法为单位进行计算。如果您采用这种方法,请确保integer类型足够大,能够表示您将在程序中使用的所有值。对于这里展示的谜题,int就足够了。下面是我们用int类型表示货币值分钟后重写的println语句。这个版本将打印出正确答案90分:
解决这个问题的另一种方法是使用BigDecimal,它执行精确的小数运算。它还可以通过JDBC与SQL十进制类型进行互操作。这里提醒一句:一定要用BigDecimal(String)构造函数,千万不要用BigDecimal(double)。后一个构造函数将用其参数的确切值创建一个实例:new BigDecimal(1)将返回01000000000005115123125782702181583404541015625 BigDecimal的表示。通过正确使用BigDecimal,程序可以打印出我们预期的结果0.90:
导入Java . math . bigdecimal;
公共类更改{
公共静态void main(String args[]){
system . out . println(new bigdecimal(2.00 )
subtract(new BigDecimal( 1.10 ));
}
}这个版本并不完美,因为Java并没有为BigDecimal提供任何语言支持。使用
BigDecimal的计算很可能比那些使用原类型的要慢,这对于一些使用大量小数计算的程序来说可能会成为一个问题,但对于大多数程序来说,这根本不重要。
总之,在需要确切答案的地方,避免使用float和double对于货币计算,使用int、long或BigDecimal。语言设计者应该考虑为十进制操作提供语言支持。一种方法是为运算符重载提供有限的支持,以便运算符可以处理数字引用类型,如BigDecimal。另一种方法是提供原始的十进制类型,就像COBOL和PL/I一样。
谜题二:找零时刻
这个谜题之所以叫长整除,是因为涉及的程序是关于两个长值的整除。股息代表一天中的微秒数;除数代表一天中的毫秒数。这个程序会打印出什么?
公共类延长{
公共静态void main(String args[]){
每天最终长微=24 * 60 * 60 * 1000 * 1000;
每天最终长毫=24 * 60 * 60 * 1000;
Systemoutprintln(微/毫/天);
}
}这个拼图看起来挺直观的。每天的毫秒数和微秒数是常数。为了清楚起见,它们都表示为产品。每天的微秒数是(24小时/天*60分钟/小时*60秒/分钟*1000毫秒/秒*1000微秒/毫秒)。每天的毫秒数之差只是1000的最后一个因子。当你用每天的微秒数除以每天的毫秒数时,除数中的所有因子都被四舍五入,只剩下1000,这正好是每毫秒的微秒数。
除数和被除数都是长整型。长型大到可以轻松保存这两个产品而不会溢出。因此,看起来程序必须打印1000个。不幸的是,它打印5。这里到底发生了什么?
问题是,每天的常量MICROS的计算确实“溢出”。虽然计算出来的结果适合放在long中,而且还有空间,但是不适合放在int中。这个计算完全是由int操作完成的,只有在操作完成后,结果才提升为long,为时已晚:计算已经溢出,它返回一个小200倍的值。从int升级到long是一个扩大的原语转换,它保留了(不正确的)数值。然后这个值被每天的毫微微数整除,每天的毫微微数的计算是正确的,因为它适合于int运算。这样,除法的结果是5。
那么为什么用int运算进行计算呢?所有相乘的因子都是int值。当你把两个int值相乘,你会得到另一个int值。Java没有目标类型确定的特性,这是一种语言特性。这意味着存储结果的变量类型将影响计算中使用的类型。
通过使用long常量代替int常量作为每个乘积的第一因子,我们可以很容易地修改这个程序。这将强制表达式中的所有后续计算都用长运算来完成。虽然这仅在每天微表达式中是必要的,但在两种产品中都是这样做的好方法。同样,并不总是需要使用long作为产品的“第一”值,但这样做也是一种很好的形式。在两个计算中都以长值开始可以清楚地表明它们都不会溢出。以下程序将打印出预期的1000:
公共类延长{
公共静态void main(字符串参数[)
每天最终长时间=24L*60*60*1000*1000:
每天最终长毫=24L * 60 * 60 * 1000
systemoutprintlnpomis PER DAY mills PER DAY);
}
}教训很简单:当你处理非常大的数字时,要小心溢出——它是一个无声的杀手。即使用于保存结果的变量足够大,也不意味着产生结果的计算是正确的类型。当你不确定时,使用长运算来执行整个计算。
语言设计者可以从中吸取的教训是,降低静默溢出的可能性可能是值得的。这可以通过为不产生静默溢出的操作提供支持来实现。程序可以抛出异常,而不是直接溢出。就像Ada所做的那样,或者当需要防止溢出时,它们可以自动切换到更大的内部表示,就像Lisp所做的那样。这两种方法都可能遭受相关的性能损失。减少静默溢出的另一种方法是支持目标类型,但是这样做会大大增加类型系统的复杂性。
谜题三:长整数
拜托,之前的谜题有点棘手,但是是关于整除的。大家都知道整除很麻烦。所以下面的程序只涉及加法。它会打印什么?
公立小学班{
public static void main(String]args){
system outprintln(1234554321);
}
}从表面上看,这是一个非常简单的难题——简单到不用纸笔就能解决。加号左操作数的位按从1到5的升序排列,而右操作数按降序排列。因此,相应位的和仍然是常数,程序必须打印66666。这个分析只有一个问题:当您运行程序时,它打印17777。Java是否对打印如此非凡的数字有偏见?不知何故,这似乎不是一个合理的解释。
事情往往和表象不一样。以这个问题为例,它没有打印出我们想要的输出。请仔细观察运算符的两个操作数。我们向长类型54321添加了一个int类型12345。请注意左操作数开头的数字1和右操作数结尾的小写字母1之间的细微差别。数字1的横线(称为“臂”)和竖线(称为“干”)之间有一个锐角,而与之相反,小写字母l的臂和干之间有一个直角。
你在喊“恶心!”之前,你应该已经注意到这个问题确实引起了混乱。这里确实有一个教训:在长文字常量中,一定要用大写的L,千万不要用小写的1。这样就彻底切断了这个谜题造成混乱的源头。
system . out . println(12345 5432 l);同样,避免使用单个1字母作为变量名。例如,我们很难通过观察下面的代码段来判断它打印出的是列表1还是数字1。
list l=new ArrayList string();
l . add( Foo );
system . outprintln(1);
简而言之,小写字母L和数字1在大多数打字机字体中几乎是一样的。为了避免程序读者混淆这两者,不要使用小写的1作为长常量的结尾或变量名。从Java C编程语言继承了很多,包括长文字常量的语法。也许允许用小写的1来写long的文字常量是一个错误。
谜题四:初级问题
以下程序将两个十六进制(hex)文字常量相加,然后打印出十六进制结果。这个程序会打印出什么?
公共类JoyOfHex{
公共静态void main(String[] args){
System.out.println(
long . tohexstring(0x 100000000 l0x cafe babe));
}
}显然程序应该打印出1cafebabe。毕竟这真的是十六进制数1000000016和cafebabe16的和。程序采用长运算,可以支持16位十六进制数,所以不可能出现运算溢出。
但是,如果您运行该程序,您会发现它打印cafebabe时没有任何前导1。该输出代表正确结果的低32位,但第33位不知何故丢失了。
好像是程序执行的是int运算而不是long运算,或者是忘记加第一个操作数了。这里到底发生了什么?
十进制文字常量有一个很好的性质,就是所有的十进制文字常量都是正的,而十六进制和八进制文字常量没有这个性质。要编写负的十进制常数,可以使用一元求反运算符(-)连接十进制文字常数。这样就可以用十进制写出int或long类型的任意值,不管是正的还是负的,负的十进制常数可以用减号明确标识。但是十六进制和八进制文字常量却不是这样。它们可以有正值和负值。如果设置了十六进制和八进制文字常量的最高位,则它们是负数。在这个程序中,数字Oxcafebabe是一个int常量,它的最高位被设置,所以它是一个负数。它等于十进制值-889275714。
这个程序执行的加法是一种“混合型计算”。左操作数的类型是long,而右操作数的类型是int。为了执行这种计算,Java通过扩大原始类型转换将int类型的值提升为long类型,然后将两个long类型相加。因为int是一个有符号整数类型,所以这个转换执行一个一致性扩展:它将int类型的负值提升为long类型的等值。此加法的右操作数0xcafebabe提升为长类型的值0xffffffffcafebabeL。然后,这个值被加到左操作数0x100000000L上。当被视为int类型时,符号扩展后右操作数的高32位是-1,而左操作数的高32位是1。将这两个数字相加将得到0,这解释了为什么在程序输出中丢失了前导1。下面显示的是带手写的加法。加法上面的数是进位。)
1111111
0xffffffffcafebabeL
0x0000000100000000L
0x00000000cafebabeL修改这个程序很简单,用一个长的十六进制文字常量来表示右边的操作数就行了。这样可以避免破坏性的符号扩展,程序可以打印出预期的结果1cafebabe:
公共类JoyOfHex{
公共静态void main(String[] args){
System.outprintln(
LongtoHexString(0x 100000000 l0x cafe babel));
}
}这个谜题的教训是:混合类型的计算可能会造成混乱,尤其是十六进制和八进制文字常量可以表示负值,而不需要显式的减号。为了避免这种困境,通常最好避免混合类型的计算。语言设计者应该考虑支持无符号整数类型,从而根除符号扩展的可能性。可能有一种论点认为应该禁用负的十六进制和八进制文字常量,但这可能会使程序员感到沮丧,他们经常使用十六进制文字常量来表示符号没有重要意义的数值。
推荐:以上《java视频教程》是整理和分享Java语言表达式五大困惑的详细内容。更多请关注我们的其他相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。