Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 在长时间操作中测试溢出的最佳通用方法是什么?_Android_Kotlin_Entity Relationship - Fatal编程技术网

Android 在长时间操作中测试溢出的最佳通用方法是什么?

Android 在长时间操作中测试溢出的最佳通用方法是什么?,android,kotlin,entity-relationship,Android,Kotlin,Entity Relationship,在Kotlin中,与Java中一样,算术运算中没有溢出错误。我知道有一些特殊的Java操作可以测试溢出并抛出需要处理的异常 我想要一个更简单的方法。所以我想到了一个模型,虽然效率不高,但它非常简单有效 假设有人想测试2个长数字乘法:a*b 我用 if ( a.doDouble()* b.toDouble() - a*b != 0.0 ) println("Overflow") else println("Ok") 理由很简单。在Long的宇宙中,当Double不能达到所有精度时,

在Kotlin中,与Java中一样,算术运算中没有溢出错误。我知道有一些特殊的Java操作可以测试溢出并抛出需要处理的异常

我想要一个更简单的方法。所以我想到了一个模型,虽然效率不高,但它非常简单有效

假设有人想测试2个长数字乘法:
a*b

我用

if ( a.doDouble()* b.toDouble()  - a*b != 0.0 )
   println("Overflow")
else
   println("Ok")
理由很简单。在
Long
的宇宙中,当
Double
不能达到所有精度时,一个数字与其
Double
之间的差值总是
0
,即使是在极端值下也是如此。在这种情况下,添加或减去一个小数字甚至不会更改相等性测试:

   var l1= -Long.MAX_VALUE
   var d1 = l1.toDouble()
   if (d1-l1==0.0) println("-MaxLong")
   if (d1+100-l1==0.0) println("it still -MaxLong")
   var l2= Long.MAX_VALUE
   var d2 =l2.toDouble()
   if (d2-l2==0.0) println("MaxLong")
   if (d2+100-l2==0.0) println("it still MaxLong")
这将生成输出:

-MaxLong
it still -MaxLong
MaxLong
it still MaxLong
是正确的还是我遗漏了什么? 即使它是正确的,还有比这更好的解决方案吗

更新1:请注意,如果
Double
计算大于
longValue.MAXVALUE
,则其他可能性正在测试。然而,它失败了

   var n1= Long.MAX_VALUE/2+1 
   var n2= Long.MAX_VALUE/2+1
   println((n1.toDouble()+n2.toDouble()) - 
         Long.MAX_VALUE.toDouble()==0.0)
   println((n1.toDouble()+n2.toDouble()) > Long.MAX_VALUE.toDouble())
它打印:

true
false
更新2:虽然我的解决方案似乎有效,但它不起作用! ,在他接受的答案中指出以下情况:

  val lo1 = Long.MAX_VALUE - 600
  val lo2 = 100L
  var do1: Double = lo1.toDouble()
  var do2:Double = lo2.toDouble()
  var d= do1+do2
  var l=lo1+lo2  
  println(d-l==0.0)  
由于结果在
Long
范围内,它应该给出
true
,但它给出
false
,因为
Double
计算不精确

正如他所说,最好的方法是真正使用封装在用户函数中的特殊函数,如
multiplyExact

不幸的是,从API 24开始,它的资源只能在Android中使用,因此它依赖于另一个解决方案,即测试反向操作

例如,在乘法运算中,我们应该:

   var a = Long.MIN_VALUE 
   var b = -1L
   var c = a*b
   if (b!=0 && c/b != a) 
    println("overflow $c")
   else
    println("ok $c")
它打印溢出-9223372036854775808

在传统的运算中,通常涉及加法、减法和乘法,它们是函数
addExact
subtractExact
multipyExact
的对象,如前所述,这些函数很容易使用逆运算进行模拟


否定(
inv()
)还具有
negateExact
函数来处理
Long.MIN_值的否定,该函数无效,因为它没有正的对应项。评论较少的是分区,它在Java中没有专门的函数来引导溢出。但是,它在一种情况下会出现问题:
Long.MIN\u VALUE/-1
无效。

您应该知道Long数据类型具有固定的字节数

长数据类型是64位带符号的2的补码 整数。它的最小值为-9223372036854775808,并且 最大值为9223372036854775807(含)。使用这些数据 当需要比int提供的值范围更宽的值时,请键入

在漫长的宇宙中,一个数字和它的两倍之间的差值总是0

不,不是真的

println(Long.MAX_VALUE)
println(BigDecimal(Long.MAX_VALUE.toDouble()))
印刷品

9223372036854775807
9223372036854775808
您试图检查以下内容:

var l2= Long.MAX_VALUE
var d2 =l2.toDouble()
if (d2-l2==0.0) println("MaxLong")
但问题是JVM上的算术运算(实际上在大多数语言中)只能在相同类型的值上工作,因此编译器插入
toDouble()
,您就可以真正计算
d2-l2.toDouble()

如果你想要一个简单的测试,你可以这样做

val product = a*b
if ((b != 0 && product/b != a) || (a == Long.MIN_VALUE && b == -1)) {
    println("Overflow")
} else {
    // can use product here
    println("OK")
}
但实际上,使用
multipyexact
而不是手动操作更有意义。或者使用Kotlin的可空类型并定义

fun multiplyExact(x: Long, y: Long): Long? = 
    try { java.math.multiplyExact(x, y) } catch (e: ArithmeticException) { null }

编辑:为了在测试中演示一个错误,考虑加法(我很肯定它也是错误的乘法,但很难找到合适的数字):< /P>


原因是
largeNumber.toDouble()+smallNumber.toDouble()==largeNumber.toDouble()
(largeNumber+smallNumber.toDouble()==Long.MAX\u VALUE.toDouble()

也许使用Yes,我知道,但我不想抛出异常。我想避免它。不幸的是,
Long
类型不能像
Double
那样工作。计算结果不会给出无穷大,它只是在字节大小内进行运算,并给出一个似乎有点不寻常的结果。例如,在中,如果使用
2L
添加
Long.MAX_值
,则结果是
-Long.MAX_值
!我同意你说的一切,但我的测试仍然有效。如果第一个表达式不带
BigDecimal
Long.MAX\u VALUE.toDouble()-Long.MAX\u VALUE==0.0
),则为true。所以我的策略仍然有效,即使内部表示不同。如果
doubleVar-longVar
测试真的是
doubleVar-longVar.toDouble()
,这并不重要。长溢出计算结果与适当的双重计算结果非常不同。但是,你是对的,它更能用精确的函数封装检查。请参阅编辑以演示测试失败(至少是添加)。
var l2= Long.MAX_VALUE
var d2 =l2.toDouble()
if (d2-l2==0.0) println("MaxLong")
val product = a*b
if ((b != 0 && product/b != a) || (a == Long.MIN_VALUE && b == -1)) {
    println("Overflow")
} else {
    // can use product here
    println("OK")
}
fun multiplyExact(x: Long, y: Long): Long? = 
    try { java.math.multiplyExact(x, y) } catch (e: ArithmeticException) { null }
val largeNumber = Long.MAX_VALUE - 600
val smallNumber = 100L
// prints true, even though there's no overflow
println((largeNumber.toDouble() + smallNumber.toDouble()) - (largeNumber + smallNumber) != 0.0)