Kotlin behaves weird in identity of boxed and unboxed numbers - android

In my algorithm, I have been checking identify of the int variable and nullable int,
var literal_num: Int = 1000
var literal_num_boxed: Int? = literal_num
println("***********************************")
println((literal_num === literal_num_boxed)) //print false
println("***********************************")
but when you change the number to 100 the identity is equal, am i doing wrong here?
var literal_num: Int = 100
var literal_num_boxed: Int? = literal_num
println("***********************************")
println((literal_num === literal_num_boxed)) //true
println("***********************************")
I tried the same in the kotlin documentation. its also behaving the same. check the following images.
After i edited the number to 100 it behaves the in a different way.

This is because Integer.valueOf has caches.
When you use === to compare int and Int?, autobox happens and it calls Integer.valueOf.
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
From Integer.java. low is -128 and high is 127 by default.
When autobox happens, every number from -128 to 127 will share a same Integer and your result will be true. If a number isn't in that range, a new Integer will be created and your result will be false.
Related design patterns: https://java-design-patterns.com/patterns/flyweight/

Related

check if a number is decimal or integer in kotlin

I would like to know how I can identify a number as decimal or integer, I was already researching how to do it but I run into some problems when using it in an if else conditional, it gives me the following error:
Operator '==' cannot be applied to 'Float' and 'Int'.
When requesting the data from the user, I save it as Float and when placing it in the conditional it generates that error. Does anyone know how I can request a number and then check if it is integer or has decimal? By the way I am using kotlin
Code:
fun main(){
val number01 = readLine()!!.toFloat()
if (number01 % 1 == 0){ // A X + B = 0
println("Solution 1: $number01")
}else{
println("Solution 2: $number01")
}
}
I already looked on the internet how to know if it is an integer or if it is a number with decimal but when using it in a conditional it generates an error.
the output from number01%1 is Float and your using == to a Int
.To correct that you have to change your code into:
fun main(){
val number01 = readLine()!!.toFloat()
if (number01 % 1 == 0f){
println("Solution 1: $number01")
}else{
println("Solution 2: $number01")
}
}

I don't understand why "return" doesn't return a value [duplicate]

This question already has answers here:
Kotlin: Variable 'result' must be initialized
(3 answers)
Kotlin variable usage "variable must be initialize"
(1 answer)
Closed last month.
I'm new to kotlin and I don't know English well so "Google Translate hello!".
I want to return the values that I received during the execution of the if condition. This function iterates through the columns in the excel table until it finds the one I need and returns its number
I tried to write return#getTableValue to indicate where to return the value, but it didn't give anything, I don't understand, help
My code:
private fun getTableValue(xlWs: Sheet, groupe: String, dopgroupe: String): Int {
var gr: String
var cellNumb: Int
var res: Int
for (i in 0..20){
gr = xlWs.getRow(0).getCell(i).toString()
if (gr == groupe){
cellNumb = i
if (dopgroupe == "1") {
res = cellNumb
}
if (dopgroupe == "2") {
res = cellNumb + 2
}
}
}
return res // Error Variable 'res' must be initialized
}
You only set res inside if statements, so the compiler cannot be sure that you ever set a value to res. You can only use a variable’s value after it is guaranteed to have been set to something. In this case, the easiest solution is to give the variable an initial value at the declaration site, like this:
var res: Int = 0

Create list/array of Textviews to change .text via index

So I was hoping to make a list/array of textviews so that I can iterate a loop and set the .text value of the TextViews as I go. Otherwise I would have to set the values in the code statically which would be a whole lot messier and potentially not even feasible for my needs.
So in the code below the idea would be to iterate the loop and when the correct value is confirmed that [index] would then set the corresponding
var refillToken : Double = (0).toDouble()
var tweetStored : BooleanArray = BooleanArray(20)
var tweetActive : BooleanArray = BooleanArray(20)
var userID: MutableList<String> = mutableListOf("")
var textViewToken = 0
while (refillToken > 0) {
var token: Int = 0
while (token < (tweetStored.size)) {
if (tweetStored[token] == true) {
tweetActive[token] = true
textView[textViewToken].text = userID[token]
textViewToken++
refillToken--
token++
if (refillToken < 0) {
break
}
}
}
}
}
I know my loop is probably messy by sane people standards but it makes sense to me and (hopefully) isn't the issue at play. Have found a few articles or ideas searching for the past two hours but they're either 10 years old (and I think deprecated), for java or don't work for whatever reason.
You need to get a value and then add it to the textview and change this value after every action on the page.
Use variable assignment for this task

Kotlin float number with 2 decimals to string without precision loss

In Android-Kotlin I am getting float number from backend (for example num = 10000000.47)
When I try to String.format it and add that number in my balanceTextview it shows it with exponent (something like 1.0E10).
I want to show number normally without exponent and with 2 decimals. (Without presicion loss!)
Tried to use DecimalFormat("#.##") but it didn't help me. Maybe I'm doing something wrong?
num = 10000000.47f
val dec = DecimalFormat("#.##")
var result = dec.format(num)
my result is: 10000000
It losts my decimal places
The issue is your number type. According to the documentation:
For variables initialized with fractional numbers, the compiler infers the Double type. To explicitly specify the Float type for a value, add the suffix f or F. If such a value contains more than 6-7 decimal digits, it will be rounded.
With an example that shows how information may get lost:
val pi = 3.14 // Double
val e = 2.7182818284 // Double
val eFloat = 2.7182818284f // Float, actual value is 2.7182817
If the value is specified as Double instead of Float, i.e.
val num = 10000000.47
instead of
val num = 10000000.47f
then your approach works as expected, but could be shortened to:
"%.2f".format(num)
(note that the shorter version will also print "100" as "100.00" which is different from your approach but potentially still desired behaviour)
If you receive a Float from the backend then the information is already lost on your side. Otherwise you should be able to fix the issue by improved parsing.
The extension function format is only available in the JVM. In Kotlin/native, you can use this instead:
fun Float.toPrecision(precision: Int) =
this.toDouble().toPrecision(precision)
fun Double.toPrecision(precision: Int) =
if (precision < 1) {
"${this.roundToInt()}"
} else {
val p = 10.0.pow(precision)
val v = (abs(this) * p).roundToInt()
val i = floor(v / p)
var f = "${floor(v - (i * p)).toInt()}"
while (f.length < precision) f = "0$f"
val s = if (this < 0) "-" else ""
"$s${i.toInt()}.$f"
}

What it is the best general way for testing overflow in Long operations?

In Kotlin, as in Java, there is no overflow error in arithmetic operations. I know that there are special Java operations that test overflow and throw exceptions that need to be handled.
I would want a simpler way. So I thought of a model, which is not so efficient, but it is very simple and effective.
Suppose someone wants to test a 2 long numbers multiplication: a * b
I use
if ( a.doDouble()* b.toDouble() - a*b != 0.0 )
println("Overflow")
else
println("Ok")
The justification is simple. Within the universe of Long the difference between a number and its Double is always 0, even at extreme values, when the Double does not reach all precision. In this case, adding or subtracting a small number does not even change the equality test:.
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")
This generates the output:
-MaxLong
it still -MaxLong
MaxLong
it still MaxLong
Is it correct or I'm missing something?
Even if it's correct, is there any other solution better than this?
Update 1: Notice that other possibility is testing if Double calculation is greater that longValue.MAXVALUE. However, it fails!
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())
It prints:
true
false
Update 2: Although my solution seems to work, it doesn't!
Alexey Romanov, points me in his accepted answer the following situation:
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)
As the result is inside Long range, it should gives true, but it gives false, because Double calculation is not exact!
As he said, the best way is really using special functions like multiplyExact encapsulated in an user function.
Unfortunately, its resources only can be used in Android from API 24 onwards, so it rests the other solution from Alexey Romanov, that consists in test the inverse operation.
So, for instance, in the multiplication one should do:
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")
It prints overflow -9223372036854775808
Among traditional operations, there are usually concerns with addition, subtraction, and multiplication, which are the object of the functions addExact, subtractExact, multipyExact functions, that are easily emulated using inverse operations, as cited.
Negation (inv()) also has the negateExact function to deal with the negation of Long.MIN_VALUE, which is invalid as it has no positive counterpart. Less commented is the division, which has no specialized function in Java to lead with overflow. However it gives problem in a single case: Long.MIN_VALUE / -1 is invalid.
Within the universe of Long the difference between a number and its Double is always 0
No, not really.
println(Long.MAX_VALUE)
println(BigDecimal(Long.MAX_VALUE.toDouble()))
prints
9223372036854775807
9223372036854775808
You tried to check this:
var l2= Long.MAX_VALUE
var d2 =l2.toDouble()
if (d2-l2==0.0) println("MaxLong")
But the problem is that arithmetic operations on JVM (and in most languages, really) can only work on values of the same type, so the compiler inserts toDouble() and you really calculate d2 - l2.toDouble().
If you want a simple test, you can do
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")
}
but really, using multiplyExact instead of doing it manually makes more sense. Or use Kotlin's nullable types and define
fun multiplyExact(x: Long, y: Long): Long? =
try { java.math.multiplyExact(x, y) } catch (e: ArithmeticException) { null }
EDIT: to demonstrate a fault in your test, consider addition (I am pretty sure it's wrong for multiplication as well, but it's harder to find suitable numbers):
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)
The reason is that largeNumber.toDouble() + smallNumber.toDouble() == largeNumber.toDouble() while (largeNumber + smallNumber).toDouble() == Long.MAX_VALUE.toDouble().
You should know that Long DataType has a fixed number of bytes Oracle Docs
The long data type is a 64-bit signed two's complement
integer. It has a minimum value of -9,223,372,036,854,775,808 and a
maximum value of 9,223,372,036,854,775,807 (inclusive). Use this data
type when you need a range of values wider than those provided by int.
//if it is not within the range then its an overflow (infinity/undefined)
if(a*b < Long.MIN_VALUE || a*b > Long.MAX_VALUE)
println("Overflow")
else
println("Ok")
Edit
Truly and unfortunately the above method is not reliable. See below table from a run test on android studio with JDK 8
##### Overflow Test #########
Long.MAX_VALUE = 9223372036854775807
Long.MIN_VALUE = -9223372036854775808
Long.MAX_VALUE - 2 = 9223372036854775805
Long.MAX_VALUE - 1 = 9223372036854775806
Long.MAX_VALUE - 0 = 9223372036854775807
Long.MAX_VALUE + 0 = 9223372036854775807
Long.MAX_VALUE + 1 = -9223372036854775808
Long.MAX_VALUE + 2 = -9223372036854775807
Long.MAX_VALUE * 2 = -2
Long.MAX_VALUE / 2 = 4611686018427387903
Long.MIN_VALUE - 2 = 9223372036854775806
Long.MIN_VALUE - 1 = 9223372036854775807
Long.MIN_VALUE - 0 = -9223372036854775808
Long.MIN_VALUE + 0 = -9223372036854775808
Long.MIN_VALUE + 1 = -9223372036854775807
Long.MIN_VALUE + 2 = -9223372036854775806
Long.MIN_VALUE * 2 = 0
Long.MIN_VALUE / 2 = -4611686018427387904
Long.MIN_VALUE + Long.MAX_VALUE = -1
Long.MAX_VALUE - Long.MIN_VALUE = -1
Long.MAX_VALUE * Long.MIN_VALUE = -9223372036854775808
Long.MAX_VALUE / Long.MIN_VALUE = 0
Long.MIN_VALUE / Long.MAX_VALUE = -1
Long.MAX_VALUE + Long.MAX_VALUE = -2
Long.MIN_VALUE + Long.MIN_VALUE = 0
Double.MAX_VALUE = 1.7976931348623157E308
Double.MAX_VALUE * 2 = Infinity
Double.MAX_VALUE + Double.MAX_VALUE = Infinity
Long.MAX_VALUE * Double.MAX_VALUE = Infinity
Double.MAX_VALUE > Long.MAX_VALUE = true
Double.MIN_VALUE < Long.MIN_VALUE = true
Looking at the log you would notice anytime Long.MAX_VALUE reaches its peak instead of hitting Infinity like Double.MAX_VALUE, the bit is switched and its next value becomes Long.MIN_VALUE and it goes on and on like that.
So now we see why the above method isn't reliable. Hence we can assume that in java Long is a DataType with zero Infinity.
Method modified introducing floating point constants in-between
//using floating points forces larger memory allocation
//this prevents bit switch after crossing max or min value of Long
if(a * 1.0 * b < Long.MIN_VALUE || a * 1.0 * b > Long.MAX_VALUE)
println("Either a Double or Long Overflow")
else
println("Ok")

Categories

Resources