Java 三元运算符导致的意外类型
我正在尝试编写一个方法,该方法获取一个Java 三元运算符导致的意外类型,java,ternary-operator,Java,Ternary Operator,我正在尝试编写一个方法,该方法获取一个double,验证数字是否在点后面,如果返回double,如果不返回int public class Solution { public static void main(String[] args) { double d = 3.000000000; System.out.println(convert1(d)); System.out.println(convert2(d)); }
double
,验证数字是否在点后面,如果返回double
,如果不返回int
public class Solution {
public static void main(String[] args) {
double d = 3.000000000;
System.out.println(convert1(d));
System.out.println(convert2(d));
}
static Object convert1(double d) {
if(d % 1 == 0)
return (int) d;
else
return d;
}
static Object convert2(double d) {
return ((d%1) == 0) ? ((int) (d)) : d;
}
}
输出:
3
3.0
所以,我想要的一切都发生在方法
convert1()
中,但不会发生在方法convert2()
中。看来这些方法必须做同样的工作。但是我做错了什么?三元运算符要求两个结果值的类型相同,因此int
将自动(安全)加宽转换为double
三元函数与它的
if
“等价物”并不完全相同。您看到的效果与类似
Java使用三元运算符处理类型的方式与使用if
语句处理类型的方式略有不同
具体而言,委员会:
条件表达式的类型确定如下:
否则,如果第二个和第三个操作数的类型为
可转换(§5.1.8)为数字类型,则有几种情况:
否则,二进制数字提升(§5.6.2)适用于
操作数类型,条件表达式的类型为
第二个和第三个操作数的升级类型
翻到标准的那一页:
如果其中一个操作数的类型为double,则另一个操作数将转换为double
这就是这里发生的事情,然后自动装箱到一个Double
。在解释差异的if
语句中,似乎没有发生这种转换
更广泛地说,这不是一个好主意。我认为根据值返回int
或double
中的一个不是一个好的设计——如果您想舍入某个值,请使用Math.floor
,如果您不想打印小数,请使用printf
编辑:我不认为这是一个好主意做黑客的事情,以绕过常规的数字转换系统。这里有一个想法可以直接为您提供一个字符串
,它似乎就是您想要的:
static String convert3(double d) {
return ((d % 1 == 0) ? Integer.toString((int)d) : Double.toString(d));
}
正如其他答案所述,这种行为是因为三元表达式的两个可能结果必须具有相同的类型 因此,要使三元版本与
convert1()
的工作方式相同,只需将int
强制转换为对象
:
static Object convert2(double d) {
return ((d % 1) == 0) ? ((Object) (int) (d)) : d;
}
要解决点后数字的问题,请执行以下操作:
public Object convert(double number){
double whole = Math.floor(number);
if(Math.abs(whole - number) < DELTA){
return (int) number;
}
return number;
}
公共对象转换(双倍数字){
双整数=数学楼层(数字);
if(数学绝对值(整数)
DELTA
是足够小的常量,可以解决浮点格式编码的整数的问题
我已经根据记忆编写了代码,但我认为背后的想法很清楚。谢谢您提供了非常详细的答案。我需要这个GUI方法,因此我既不能使用Mats.floor也不能使用printf。@user3922109您的用例是什么?转换为两种不同的数字类型中的一种几乎肯定不是可行的方法。您需要的字符串是带小数还是不带小数?@user3922109我在一个示例中添加了将其直接转换为
字符串
,这似乎正是您所需要的。+1表示这不是一个好主意。我不认为根据值返回int或double中的一个是好的设计-这是我看到OP时想到的第一件事example@vaxquis是的,OP似乎极有可能再次(再次)受到数字促销规则的影响。如果他需要一个字符串,他应该使用一个字符串。完全脱离了这个问题的主题,但您是否知道,由于浮点不准确,几乎所有表示为双精度的整数都将是该整数值?也就是说,我希望你会经常得到x.0
,而你却没有想到。这个运算符实际上被称为条件运算符,如@Patrick Collins@Heuster的回答所示。这是一个常见的误解。实际上,许多整数值精确地转换为双精度。尤其是绝对值低于2^53 IIRC的所有,这比所有32位整数都多。只有经过一些转换或某些类型的操作后,才会失去精度。(加法、减法和范围内乘法都可以。)@MichaelAnderson:任何双精度运算要么足够小,如果它是一个整数,就会非常精确;要么太大,以至于精度不会超过小数点。注意,丢失大浮点数的精度不能使其成为非整数。(是的,极限是2^53)。@MichealAnderson好的,也许我的措辞有点太强了,这不仅仅发生在整数运算中。但是,由于这里的问题是看一个数字是否为整数,我们可以安全地假设OP不限于整数。例如,这个问题肯定会发生在10*0.1
上。你可以做得稍微好一点,并将其转换为数字,对吗?@Chris:是的,我只是演示了机制如何使其与convert1()
相同,后者返回对象。对于这样的方法,Number
或String
可能是更符合逻辑的返回值。