Scala: Converting a Double from Scientific Notation without losing precision? - scala

I'd like to convert a double such as 1.1231053E7 to 11,231,053.0 in scala. Currently the way I am converting doubles is to do this f"$number" where number is a double value. Unfortunately this just gives me a string with 1.1231053E7.
I can convert it out of scientific notation using NumberFormat or DecimalFormat but these also force me to choose a predetermined precision. I want flexible precision. So...
val number1 = 1.2313215
val number2 = 100
val number4 = 3.333E2
... when converted should be...
1.2313215
100
333.3
Currently DecimalFormat makes me choose the precision during construction like so: new DecimalFormat(##.##). Each # after . signifies a decimal point.
If I use f"$number", it treats the decimal points correctly but, like I said before, it is unable to handle the scientific notation.

Just decide how many places after the . you need, write out the number hiding the zeros:
val fmt = new java.text.DecimalFormat("#,##0.##############")
for (x <- List[Double](1.2313215, 100, 3.333E2)) println(fmt.format(x))
prints:
1.2313215
100
333.3

Related

In Dart, how do you set the number of decimals in a double variable? [duplicate]

This question already has answers here:
How do you round a double in Dart to a given degree of precision AFTER the decimal point?
(28 answers)
Closed last year.
I want to set a double, let's call it Price, in Dart, so that it always gives me a double of 2 decimal places.
So 2.5 would return 2.50 and 2.50138263 would also return 2.50.
The simplest answer would be double's built-in toStringAsFixed.
In your case
double x = 2.5;
print('${x.toStringAsFixed(2)}');
x = 2.50138263;
print('${x.toStringAsFixed(2)}');
Would both return 2.50. Be aware that this truncates (e.g., 2.519 returns 2.51). It does not use the standard rounding (half-even) banker's algorithm.
I recommend using a NumberFormat from the intl package; The parsing and formatting rules are worth learning since they appear in other languages like Java.
double d = 2.519;
String s = NumberFormat.currency().format(d);
print(s);
returns USD2.52
s = NumberFormat('#.00').format(d);
returns 2.52
Since your are dealing with money, you should probably use NumberFormat.currency, which would add the currency symbol for the current locale.
Your question is more about how Dart handles the type double. Something like the following might work depending on your use-case:
void main() {
double num = 2.50138263;
num = double.parse(num.toStringAsFixed(2));
print(num);
}
More info about how Dart handles double can be found here.

Issue with Double datatype in Scala

New to Scala and am trying to come up with a library in Scala to check if the double value being passed is of a certain precision and scale. What I noticed was that if the value being passed is 1.00001 then I get the value as that in my called function, but if the value being passed is 0.00001 then I get the value as 1.0E-5, Is there any way to preserve the number in Scala?
def checkPrecisionAndScaleFormat(precision: Int, scale: Int)(valueToCheck: Double): Boolean = {
val value = BigDecimal(valueToCheck)
value.precision <= precision && value.scale <= scale
}
What I noticed was that if the value being passed is 1.00001 then I get the value as that in my called function, but if the value being passed is 0.00001 then I get the value as 1.0E-5
From your phrasing, it seems like you see 1.00001 and 1.0E-5 when debugging (either by printing or in the debugger). It's important to understand that
this doesn't correspond to any internal difference, it's just how Double.toString is defined in Java.
when you do something like val x = 1.00001, the value isn't exactly 1.00001 but the closest number representable as a Double: 1.000010000000000065512040237081237137317657470703125. The easiest way to see the exact value is actually looking at BigDecimal.exact(valueToCheck).
The only way to preserve the number is not to work with Double to begin with. If it's passed as a string, create the BigDecimal from the string. If it's the result of some calculations as a double, consider doing them on BigDecimals instead. But string representation of a Double simply doesn't carry the information you want.

Absolute function

In my program I am using Bigdecimal to truncate numbers and storing them in a variable. Eg. 123.456789 is getting displayed as 123.45.Further I am trying to find the absolute of the numbers.The problem arises here i.e - 123.45 should appear as 123.45 but it's appearing as 123.4589Egh.Can someone please help as to how can I find absolute of numbers.
var diff1=BigDecimal(diff).setScale(2, BigDecimal.RoundingMode.HALF_UP).toDouble
var bigdec=abs(diff1)
Try taking inputs for 10-15 numbers in an array (in diff variable)
Uhm, I'm not sure what your problem is, but for me this works fine:
val diff = -123.456789
var diff1 = BigDecimal(diff).setScale(2, BigDecimal.RoundingMode.DOWN).toDouble
var bigdec = Math.abs(diff1)
println(bigdec) // 123.45
Note that if you want 123.45 instead of 123.46 you have to change your rounding mode.
Taking in an array doesn't change anything, although you need to make a def and map over the array now when rounding - as you cannot call the BigDecimal apply function on an Array:
// generates an Array of 20 elements with random doubles from 0 to 200
val diff = Array.fill(20)(math.random).map(_ * 200)
.map { num => // using this map function to make some negatives
if (num < 100) num * -1
else num
}
def round(double: Double) = BigDecimal(double)
.setScale(2, BigDecimal.RoundingMode.HALF_UP)
.toDouble
var absolute = diff.map(num => Math.abs(round(num)))
Does the above code reflect what you are doing? If so, for var absolute I am getting an Array[Double] with positive numbers and only 2 decimal places.

How to round up a number if it's not an integer?

I want to calculate a simple number, and if the number is not an integer I want to round it up.
For instance, if after a calculation I get 1.2, I want to change it to 2. If the number is 3.7, I want to change it to 4 and so on.
You can use math.ceil to round a Double up and toInt to convert the Double to an Int.
def roundUp(d: Double) = math.ceil(d).toInt
roundUp(1.2) // Int = 2
roundUp(3.7) // Int = 4
roundUp(5) // Int = 5
The ceil function is also directly accessible on the Double:
3.7.ceil.toInt // 4
Having first imported math
import scala.math._ (the final dot & underscore are crucial for what comes next)
you can simply write
ceil(1.2)
floor(3.7)
plus a bunch of other useful math functions like
exp(1)
pow(2,2)
sqrt(pow(2,2)

Swift: Double conversion inconsistency. How to correctly compare Doubles?

I have a very simple function to convert temperature from ˚C TO ˚K.
func convertKelvinToCelsius(temp:Double) ->Double {
return temp - 273.15
}
And I have a unit test to drive this function. This is where the problem is:
func testKelvinToCelsius(){
var check1 = conv.convertKelvinToCelsius(200.00) // -73.149999999999977
var check2 = 200.00 - 273.15 // -73.149999999999977
var check3 = Double(-73.15) // -73.150000000000006
//Passes
XCTAssert(conv.convertKelvinToCelsius(200.00).description == Double(-73.15).description, "Shoud convert from celsius kelvin")
//Fails
XCTAssert(conv.convertKelvinToCelsius(200.00) == Double(-73.15), "Shoud convert from celsius kelvin")
}
When you add a breakpoint and check the values of check1, check2 and check3, they are very interesting:
check1 Double -73.149999999999977
check2 Double -73.149999999999977
check3 Double -73.150000000000006
Questions:
Why does Swift return different values for check1/check2 and check3
How can I get the second test to pass, because writing it like I did the test1 smells. Why should I have to convert Doubles to Strings to be able to compare them?
Finally, when I println check1, check2 and check3, they all print to be '-73.15'. Why? Why not print accurately, and not confuse the programmers!?
To Reproduce:
Just type 200 - 273.15 == -73.15 in you playground and watch it go false!!
This is expected behavior for floating point values. They cannot be 100% accurately represented.
You can use the XCTAssertEqualWithAccuracy function to assert floating point values are within a given range of each other.
The reason println prints the same value for all is because it internally rounds them to two decimals (I assume).
This is not a Swift specific issue, this is related to the fact how decimal numbers are created in computers and what is their precision. You will need to work with DBL_EPSILON.
Swift, like most languages, uses binary floating point numbers.
With binary floating point numbers, some numbers can be represented exactly, but most can't. What can be represented exactly are integers unless they are very large (for example, 100000000000000.0 is fine), and such integers multiplied or divided by powers of two (7.375 is fine, it is 59.0 / 8, but 7.3 isn't).
Every floating point operation gives you the exact result, rounded to the nearest floating-point number. So you get
200.0 -> Exactly 200
273.15 -> A number very close to 273.15
200 - 273.15 -> A number very close to -73.15
-73.15 -> A number very close to -73.15
If you compare two numbers that are both very very close to -73.15 they are not necessarily equal. That's not a problem of the == operator; that one will determine correctly whether they are equal or not. The problem is that the two numbers can actually be different.