Is there any elegant ways to convert Int to BigDecimal in Kotlin? - kotlin

I'm working on my toy project with Kotlin.
While writing code, I feel that those codes are somewhat duplicated and not clean.
val a: Int = 1
val a_D: BigDecimal = a.toBigDecimal()
val b_D: BigDecimal = a.toBigDecimal()
So, is there any way to avoid those duplication(something like toBigDecimal()) using elegant way?

If you are bothered about having to create the BigDecimal over two lines, BigDecimal has constructors that take Int that you can call directly:
val bigDecimalInt = BigDecimal(1)
This is fine for integer values, BUT for floating-point values like Double the constructor and toBigDecimal actually behave differently. The constructor creates a BigDecimal value of the Double value passed in, which will be "incorrect" if that value is not exactly representable in floating-point arithmetic. toBigDecimal converts the value to a String and then uses that which gives the "correct" value
val doubleNum:Double = 0.1
println(doubleNum.toBigDecimal()) // prints 0.1
val bigDecimal:BigDecimal = BigDecimal(0.1)
println(bigDecimal) // prints 0.1000000000000000055511151231257827021181583404541015625
If none of that makes sense, you probably need to read about Floating Point Arithmetic, this is a common problem affecting all/most programming languages
So toBigDecimal is a safer option

Related

Kotlin: succinct way of inverting Int sign depending on Boolean value

I have
var x: Int
var invert: Boolean
and I need the value of the expression
if (invert) -x else x
Is there any more succinct way to write that expression in Kotlin?
There is no shorter expression using only the stdlib to my knowledge.
This is pretty clear, though. Using custom functions to make it shorter is possible, but it would only obscure the meaning IMO.
It's hard to tell which approach might be best without seeing more of the code, but one option is an extension function. For example:
fun Int.negateIf(condition: Boolean) = if (condition) -this else this
(I'm using the term ‘negate’ here, as that's less ambiguous: when dealing with numbers, I think ‘inverse’ more often refers to a multiplicative inverse, i.e. reciprocal.)
You could then use:
x.negateIf(invert)
I think that makes the meaning very clear, and saves a few characters. (The saving is greater if x is a long name or an expression, of course.)
If invert didn't change (e.g. if it were a val), another option would be to derive a multiplier from it, e.g.:
val multiplier = if (invert) -1 else 1
Then you could simply multiply by that:
x * multiplier
That's even shorter, though a little less clear; if you did that, it would be worth adding a comment to explain it.
(BTW, whichever approach you use, there's an extremely rare corner case here: no positive Int has the same magnitude as Int.MIN_VALUE (-2147483648), so you can't negate that one value. Either way, you'll get that same number back. There's no easy way around that, but it's worth being aware of.)
You could create a local extension function.
Local functions are helpful when you want to reduce some repetitive code and you want to access a local variable (in this case, the invert boolean).
Local functions are particularly useful when paired with extension functions, as extension functions only have one 'receiver' - so it would be difficult, or repetitive, to access invert if invert() wasn't a local function.
fun main() {
val x = 1
val y = 2
val z = 3
var invert = false
// this local function can still access 'invert'
fun Int.invert(): Int = if (invert) -this else this
println("invert = false -> (${x.invert()}, ${y.invert()}, ${z.invert()})")
invert = true
println("invert = true -> (${x.invert()}, ${y.invert()}, ${z.invert()})")
}
invert = false -> (1, 2, 3)
invert = true -> (-1, -2, -3)

Kotlin sum of Double or BigDecimal return unexpected result [duplicate]

This question already has answers here:
Why does floating-point arithmetic not give exact results when adding decimal fractions?
(31 answers)
Closed 11 months ago.
I'm trying to get the total amount of double values but it returns unexpected results. Check the following screenshot:
Link for the code
Code:
import java.math.BigDecimal
/**
* You can edit, run, and share this code.
* play.kotlinlang.org
*/
fun main() {
val items = listOf(MyItem(BigDecimal(3.6)), MyItem(BigDecimal(2.0)), MyItem(BigDecimal(4.3)), MyItem(BigDecimal(0.1)))
println(items.sumOf { it.amount })
}
data class MyItem(val amount: BigDecimal)
The expected result is: 10.0
The actual result is: 9.9999999999999999167332731531132594682276248931884765625
In most cases it is better to provide numbers to BigDecimal as strings, not floats:
val items = listOf(MyItem(BigDecimal("3.6")), MyItem(BigDecimal("2.0")), MyItem(BigDecimal("4.3")), MyItem(BigDecimal("0.1")))
It solves your problem.
Few words of explanation: floating-point numbers are by nature imprecise for storing decimal fractions. They only provide a close result, but not the one we would expect.
BigDecimal tries to fix this problem. It makes some tricks to represent the number as we would expect. But to do this it needs to understand how do we want to represent numbers, what is our expected precision, etc. It can deduct this from numbers provided by strings, but not from floats/doubles.
The problem is that you instantiate your BigDecimals using Double values which leads to rounding issues.
You can instead write:
val items = listOf(MyItem(BigDecimal("3.6")), MyItem(BigDecimal("2.0")), MyItem(BigDecimal("4.3")), MyItem(BigDecimal("0.1")))
Then your result is 10.0.

Kotlin - Converting Float to Double while maintaining precision

In Kotlin 123.456 is a valid Double value, however, 123.456F.toDouble() results in 123.45600128173828 - presumably just the way precision is handled between the two.
I want to be able to convert freely between the two, specifically for cases like this:
123.456F -> 123.456 // Float to Double
123.456 -> 123.456F // Double to Float
How can I convert a float to a double in cases like this, and maintain precision?
It's a big ugly, but you could convert your Float to a String and back out to a Double:
val myDouble: Double = 123.456f.toString().toDouble()
// 123.456d
You could always encapsulate this in an extension function:
fun Float.toExactDouble(): Double =
this.toString().toDouble()
val myDouble = 123.456f.toExactDouble()
In Kotlin 123.456 is a valid Double value
Actually, that's not quite true.  There's a Double value very close to 123.456, but it's not exactly 123.456.  What you're seeing is the consequences of that.
So you can't maintain precision, because you don't have that precision to start with!
Short answer:
If you need exact values, don't use floating-point!
(In particular: Never store money values in floating-point! See for example this question.)
The best alternative is usually BigDecimal which can store and calculate decimal fractions to an arbitrary precision. They're less efficient, but Kotlin's operator overloading makes them painless to use (unlike Java!).
Or if you're not going to be doing any calculations, you could store them as Strings.
Or if you'll only need a certain number of decimal places, you could scale them all up to Ints (or Longs).
Technical explanation:
Floats and Doubles use binary floating-point; they store an integer, and an integer power of 2 to multiple or divide it by.  (For example, 3/4 would be stored as 3*2⁻².)  This means they can store a wide range of binary fractions exactly.
However, just as you can't store 1/3 as a decimal fraction (it's 0.3333333333…, but any finite number of digits will only be an approximation), so you can't store 1/10 as a binary fraction (it's 0.000110011001100…).  This means that a binary floating-point number can't store most decimal numbers exactly.
Instead, they store the nearest possible value to the number you want.  And the routines which convert them to a String will try to undo that difference, by rounding appropriately.  But that doesn't always give the result you expect.
Floating-point numbers are great when you need a huge range of values (e.g. in scientific and technical use), but don't care about storing them exactly.

Why kotlin wrong: val minT: Long = -9223372036854775808L //Long.MIN_VALUE

Kotlin's Long.MIN_VALUE == -9223372036854775808, but when I write:
val minT: Long = -9223372036854775808L //Long.MIN_VALUE
IDEA say it was wrong.
Dmitry Jemerov told me this because the - sign in Kotlin is not part of the constant but rather the unary minus operator applied to the constant value, and 9223372036854775808L is one larger than the maximum possible positive value for the Long type.
But now, why Int is right :
val minI: Int = -2147483648 //Int.MIN_VALUE
Look here:
I believe they bound like that value may need to fall within -9223372036854775808 to 9223372036854775808 because of Long.

Delphi Double to Objective C double

I am looking a few hours for some solution of this problem, but I don't get how it works. I have a hex string from delphi double value : 0X3FF0000000000000. That value should be 1.0. It is 8 byte long, first bit is sign, next 11 are exponent and the rest is mantissa. So for me is this hex value equals 0 x 10^(1023). Maybe I am wrong somewhere, but it doesn't matter. The point is, I need this hex value to convert into objective c double value. If I do: (double)strtoll(hexString.UTF8String, NULL,16); I get: 4.607...x 10 ^18. What am I doing wrong?
It seems that trying to cast in this way ends up with a call to an implicit type conversion (calls _ultod3 or _ltod3) that alters the underlying data. In fact, even trying to do this seems to do the same thing :
UINT64 temp1 = strtoull(hexString, NULL, 16);
double val = *&temp1;
But if you cast the uint pointer to a double* it semes to suppress the compiler's desire to try to perform a conversion. Something like this should work :
UINT64 temp1 = strtoull(hexString, NULL, 16);
double val = *(double*)&temp1;
At least this works with the MS C++ compiler... I imagine the objective C compiler would cooperate as well.