How do I round a number in Groovy? I would like to keep 2 decimal places.
For example (pseudo-code):
round(1.2334695) = 1.23
round(1.2686589) = 1.27
If you're dealing with doubles or floats
You can simply use
assert xyz == 1.789
xyz.round(1) == 1.8
xyz.round(2) == 1.79
You can use:
Math.round(x * 100) / 100
If x is a BigDecimal (the default in Groovy), this will be exact.
Use mixin.
class Rounding {
public BigDecimal round(int n) {
return setScale(n, BigDecimal.ROUND_HALF_UP);
}
}
Add this to your startup class and round() is a first-class method of BigDecimal:
BigDecimal.mixin Rounding
Test cases:
assert (new BigDecimal("1.27")) == (new BigDecimal("1.2686589").round(2))
assert (1.2686589).round(2) == 1.27
assert (1.2334695).round(2) == 1.23
Like this:
def f = 1.2334695;
println new DecimalFormat("#.##").format(f);
Or like this:
println f.round (new MathContext(3));
Output:
1.23
Reference: Formatting a Decimal Number
Groovy adds a round() method to the Double and Float classes, so:
(123.456789f).round(2) == 123.46f
Source: Rounding Numbers in Groovy
Probably, more Groovysh way would be to use this snippet (x as double).round(2) like this:
def a = 5.2355434
println "a = $a, a.class = ${a.getClass()}"
def b = (a as double).round(2)
println "b = $b, b.class = ${b.getClass()}"
Looking at #sjtai's and #cdeszaq's answers you don't need to get mixed up with mixin if you just define a method like this:
def bigDecimalRound(n,decimals){
return(n.setScale(decimals, BigDecimal.ROUND_HALF_UP))
}
It is the BigDecimal builtin method setScale that performs the rounding.
println(1.2334695.setScale(2, BigDecimal.ROUND_HALF_UP))
>> 1.23
It's worth noting also that setScale accepts negative arguments in order to round things to larger order of magnitude, i.e.
println(123.2334695.setScale(-1, BigDecimal.ROUND_HALF_UP))
>> 1.2E+2
Working from #sjtai's great answer, this is the Mixin I use for just about all my decimal rounding needs:
class Rounding {
public BigDecimal round(int decimalPlaces = 0, RoundingMode roundingMode = RoundingMode.HALF_EVEN) {
return setScale(decimalPlaces, roundingMode);
}
}
If rounds to an int by default, and uses an "even" rounding method (reducing statistical error by default is always a good thing), but it still allows the caller to easily override these.
as simple as this:
YOUR_NUMBER = 1.234567
((int) YOUR_NUMBER * 100)/100
note: this would cut off the extra decimal points; it doesn't round up.
For example:
def rd = 1.3425345352
sd = ((float)rd).round(3)
println sd
>> 1.343
This is surprisingly complex for Groovy. It's usually... groovier.
You need to create a MathContext object to do the rounding.
num = 9.59123331333g
// rounds to 2 places, rounding up by default
mc = new java.math.MathContext(2)
num.round(mc)
==> Result: 7.0
with help from
https://blogs.oracle.com/fadevrel/rounding-numbers-and-decimal-places-in-numerical-fields
https://docs.oracle.com/javase/7/docs/api/java/math/MathContext.html
https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#round(java.math.MathContext)
You can convert any number to float and then use the round() function as:
((float)1.2334695).round(2)
Related
In the documentation of compareTo function, I read:
Returns zero if this object is equal to the specified other object, a
negative number if it's less than other, or a positive number if it's
greater than other.
What does this less than or greater than mean in the context of strings? Is -for example- Hello World less than a single character a?
val epicString = "Hello World"
println(epicString.compareTo("a")) //-25
Why -25 and not -10 or -1 (for example)?
Other examples:
val epicString = "Hello World"
println(epicString.compareTo("HelloWorld")) //-55
Is Hello World less than HelloWorld? Why?
Why it returns -55 and not -1, -2, -3, etc?
val epicString = "Hello World"
println(epicString.compareTo("Hello World")) //55
Is Hello World greater than Hello World? Why?
Why it returns 55 and not 1, 2, 3, etc?
I believe you're asking about the implementation of compareTo method for java.lang.String. Here is a source code for java 11:
public int compareTo(String anotherString) {
byte v1[] = value;
byte v2[] = anotherString.value;
if (coder() == anotherString.coder()) {
return isLatin1() ? StringLatin1.compareTo(v1, v2)
: StringUTF16.compareTo(v1, v2);
}
return isLatin1() ? StringLatin1.compareToUTF16(v1, v2)
: StringUTF16.compareToLatin1(v1, v2);
}
So we have a delegation to either StringLatin1 or StringUTF16 here, so we should look further:
Fortunately StringLatin1 and StringUTF16 have similar implementation when it comes to compare functionality:
Here is an implementation for StringLatin1 for example:
public static int compareTo(byte[] value, byte[] other) {
int len1 = value.length;
int len2 = other.length;
return compareTo(value, other, len1, len2);
}
public static int compareTo(byte[] value, byte[] other, int len1, int len2) {
int lim = Math.min(len1, len2);
for (int k = 0; k < lim; k++) {
if (value[k] != other[k]) {
return getChar(value, k) - getChar(other, k);
}
}
return len1 - len2;
}
As you see, it iterated over the characters of the shorter string and in case the charaters in the same index of two strings are different it returns the difference between them. If during the iterations it doesn't find any different (one string is prefix of another) it resorts to the comparison between the length of two strings.
In your case, there is a difference in the first iteration already...
So its the same as `"H".compareTo("a") --> -25".
The code of "H" is 72
The code of "a" is 97
So, 72 - 97 = -25
Short answer: The exact value doesn't have any meaning; only its sign does.
As the specification for compareTo() says, it returns a -ve number if the receiver is smaller than the other object, a +ve number if the receiver is larger, or 0 if the two are considered equal (for the purposes of this ordering).
The specification doesn't distinguish between different -ve numbers, nor between different +ve numbers — and so neither should you. Some classes always return -1, 0, and 1, while others return different numbers, but that's just an implementation detail — and implementations vary.
Let's look at a very simple hypothetical example:
class Length(val metres: Int) : Comparable<Length> {
override fun compareTo(other: Length)
= metres - other.metres
}
This class has a single numerical property, so we can use that property to compare them. One common way to do the comparison is simply to subtract the two lengths: that gives a number which is positive if the receiver is larger, negative if it's smaller, and zero of they're the same length — which is just what we need.
In this case, the value of compareTo() would happen to be the signed difference between the two lengths.
However, that method has a subtle bug: the subtraction could overflow, and give the wrong results if the difference is bigger than Int.MAX_VALUE. (Obviously, to hit that you'd need to be working with astronomical distances, both positive and negative — but that's not implausible. Rocket scientists write programs too!)
To fix it, you might change it to something like:
class Length(val metres: Int) : Comparable<Length> {
override fun compareTo(other: Length) = when {
metres > other.metres -> 1
metres < other.metres -> -1
else -> 0
}
}
That fixes the bug; it works for all possible lengths.
But notice that the actual return value has changed in most cases: now it only ever returns -1, 0, or 1, and no longer gives an indication of the actual difference in lengths.
If this was your class, then it would be safe to make this change because it still matches the specification. Anyone who just looked at the sign of the result would see no change (apart from the bug fix). Anyone using the exact value would find that their programs were now broken — but that's their own fault, because they shouldn't have been relying on that, because it was undocumented behaviour.
Exactly the same applies to the String class and its implementation. While it might be interesting to poke around inside it and look at how it's written, the code you write should never rely on that sort of detail. (It could change in a future version. Or someone could apply your code to another object which didn't behave the same way. Or you might want to expand your project to be cross-platform, and discover the hard way that the JavaScript implementation didn't behave exactly the same as the Java one.)
In the long run, life is much simpler if you don't assume anything more than the specification promises!
I have a file with integers for which I want the average. Below is what I came up with and it works, but was wondering if there was a better (groovier) way..
File myFile = new File("myListOfNumbers.txt")
int total = 0
int count = 0
myFile.eachLine {line->
total = Integer.parseInt(line) + total
count++
}
println "Avg is ${total /count}"
If you are looking for more declarative approach then you could do something like this:
def avg2 = myFile.readLines()
.sum({ it.toInteger() }) / myFile.readLines().size()
The only problem is that this is not very efficient, because here we are calling readLines() method twice. Of course we could split declaration from this expression to make code more efficient and then we will end up with something like this:
def lines = myFile.readLines()
def avg2 = lines.sum({ it.toInteger() }) / lines.size()
Mixing with Java 8 Stream API
Of course you can always mix Groovy approach with Java 8 approach and use built-in .average() method from Java Stream API. In this case your code would look similar to this one:
def avg1 = Files.lines(myFile.toPath())
.mapToInt({ s -> s.toInteger() })
.average()
.getAsDouble()
I hope it helps.
Groovier:
def mean = myFile.readLines().with { sum{it as Integer} / size() }
Uses groovyisms such as with and as.
Inside the closure passed to with, one can use sum() and size() directly, the target will be the object on which .with is invoked, in our case the list of lines.
Grooviest:
def mean = myFile.mean()
Of course I cheated, and did this beforehand:
File.metaClass.mean {
delegate.readLines().with { sum{it as Integer} / size() }
}
The Java way to compare two BigDecimals is to use the compareTo() method, and check if the result is -1, 0 or 1.
BigDecimal a = new BigDecimal("1.23")
BigDecimal b = new BigDecimal("3.45")
if (a.compareTo(b) > 0)) { }
I have seen that some people are using this format in grails:
if (a > b) { }
Does this work correctly? I.e. will it get the decimals correct, or is it converting to float or similar and comparing that?
How about using "==" vs using equals()?
What is the consequence of something like this:
BigDecimal a = new BigDecimal("1.00")
BigDecimal b = new BigDecimal("1")
assert (a==b)
It seems to work, but we have had it so engrained in Java not to do this kind of thing.
How about +=? e.g.
a+=b?
Would this be the same as
a = a.add(b)
Where does one find this kind of thing out? I have two groovy books, and unfortunately neither mention BigDecimal comparison or arithmetic, only the conversion/declaration.
Groovy allows overloading of operators. When a type implements certain methods then you can use a corresponding operator on that type.
For + the method to implement is plus, not add.
For greater than or less than comparisons, Groovy looks for a compareTo method on the object, and for == it looks for a method named equals. (If you want to compare references as if using == in Java, you have to use is.)
Here's a table of common math operators and the method used to overload them:
Operator Method
a + b a.plus(b)
a - b a.minus(b)
a * b a.multiply(b)
a / b a.divide(b)
a++ or ++a a.next()
a-- or --a a.previous()
a << b a.leftShift(b)
You can see that BigDecimal overloads some of these methods (you get operator overloading for plus, minus, multiply, and divide, but not for next, previous, or leftShift):
groovy:000> BigDecimal.methods*.name
===> [equals, hashCode, toString, intValue, longValue, floatValue, doubleValue,
byteValue, shortValue, add, add, subtract, subtract, multiply, multiply, divide,
divide, divide, divide, divide, divide, remainder, remainder, divideAndRemainde
r, divideAndRemainder, divideToIntegralValue, divideToIntegralValue, abs, abs, m
ax, min, negate, negate, plus, plus, byteValueExact, shortValueExact, intValueEx
act, longValueExact, toBigIntegerExact, toBigInteger, compareTo, precision, scal
e, signum, ulp, unscaledValue, pow, pow, movePointLeft, movePointRight, scaleByP
owerOfTen, setScale, setScale, setScale, stripTrailingZeros, toEngineeringString
, toPlainString, round, compareTo, getClass, notify, notifyAll, wait, wait, wait
, valueOf, valueOf, valueOf]
You get ==, >, <, >=, and <= based on how your object implements equals and compareTo.
So the operator is causing methods declared already in BigDecimal, or added to BigDecimal by groovy, to get called. It is definitely not doing any kind of conversion to a primitive type like float in order to be able to use the operators on primitives.
The table is taken from this developerworks article by Andrew Glover and Scott Davis, which has more details and includes example code.
Groovy does a wonderful job of managing numbers and to infinite precision. First thing you should know is that any number that has a dot in it is by default a BigDecimal -- the reason for the infinite precision. Here is an example of what this means exactly. Consider this snippet:
System.out.println(2.0 - 1.1);
System.out.println(new BigDecimal(2.0).subtract(new BigDecimal(1.1)));
System.out.println(new BigDecimal("2.0").subtract(new BigDecimal("1.1")));
// the above will give these:
0.8999999999999999
0.899999999999999911182158029987476766109466552734375
0.9
This shows the endurance we have to go through to get something decent in Java. In Groovy, this is all you have to do:
println 2 - 1.1
to get your 0.9! Try this on the Groovy web console. Here, the second operand is a BigDecimal, so the entire calculation is in BigDecimal, and precision is what Groovy would strive for to finish off clean in this case.
But how? This is because almost every operator in Groovy is mapped onto method calls on objects under the hood, so a + b is a.plus(b), and a==b translates to a.compareTo(b). It is therefore safe to assume what you assumed and this is the Groovy way of doing things: write less, expressively, and Groovy will do the work for you. You can learn about all this in the Groovy-lang documentation page with examples all over.
The short answer is yes, it's safe to use == for BigDecimal comparison in Groovy.
From the Groovy documentation Behaviour of == section:
In Java == means equality of primitive types or identity for objects. In Groovy == translates to a.compareTo(b)==0, if they are Comparable, and a.equals(b) otherwise. To check for identity, there is is. E.g. a.is(b).
I call an overloaded method (assertThat) which has one signature with a BigDecimal parameter and another one with double primitive parameter.
When I launch this snippet in groovy, it calls the one with BigDecimal parameter when I was expecting the double primitive parameter one to be called.
double[] erreur = Seg.erreur(xtab, ytab, 0, 2)
Assertions.assertThat(erreur[1]).isEqualTo(-0.3333333333333333)
Can someone explain me why ?
Thanks in advance.
By default, a decimal number in groovy is a BigDecimal. If you want it to be a double, you should use the suffix D or d:
From Number type suffixes in the docs:
assert 123.45 == new BigDecimal('123.45') // default BigDecimal type used
assert 1.200065D == new Double('1.200065')
Your isEqualsTo() is passing a BigDecimal as parameter, whereas your assertThat() is passing a double. Just add a d at the end of that -0.3333333333333333 and it should work:
import static org.assertj.core.api.Assertions.assertThat
class Doubles extends GroovyTestCase {
void testAssertions() {
double[] erreur = [0.1, -0.3333333333333333, 0.3]
assertThat(erreur[1]).isEqualTo(-0.3333333333333333d)
}
}
I have a String that represents an integer value and would like to convert it to an int. Is there a groovy equivalent of Java's Integer.parseInt(String)?
Use the toInteger() method to convert a String to an Integer, e.g.
int value = "99".toInteger()
An alternative, which avoids using a deprecated method (see below) is
int value = "66" as Integer
If you need to check whether the String can be converted before performing the conversion, use
String number = "66"
if (number.isInteger()) {
int value = number as Integer
}
Deprecation Update
In recent versions of Groovy one of the toInteger() methods has been deprecated. The following is taken from org.codehaus.groovy.runtime.StringGroovyMethods in Groovy 2.4.4
/**
* Parse a CharSequence into an Integer
*
* #param self a CharSequence
* #return an Integer
* #since 1.8.2
*/
public static Integer toInteger(CharSequence self) {
return Integer.valueOf(self.toString().trim());
}
/**
* #deprecated Use the CharSequence version
* #see #toInteger(CharSequence)
*/
#Deprecated
public static Integer toInteger(String self) {
return toInteger((CharSequence) self);
}
You can force the non-deprecated version of the method to be called using something awful like:
int num = ((CharSequence) "66").toInteger()
Personally, I much prefer:
int num = 66 as Integer
Several ways to do it, this one's my favorite:
def number = '123' as int
As an addendum to Don's answer, not only does groovy add a .toInteger() method to Strings, it also adds toBigDecimal(), toBigInteger(), toBoolean(), toCharacter(), toDouble(), toFloat(), toList(), and toLong().
In the same vein, groovy also adds is* eqivalents to all of those that return true if the String in question can be parsed into the format in question.
The relevant GDK page is here.
I'm not sure if it was introduced in recent versions of groovy (initial answer is fairly old), but now you can use:
def num = mystring?.isInteger() ? mystring.toInteger() : null
or
def num = mystring?.isFloat() ? mystring.toFloat() : null
I recommend using floats or even doubles instead of integers in the case if the provided string is unreliable.
Well, Groovy accepts the Java form just fine. If you are asking if there is a Groovier way, there is a way to go to Integer.
Both are shown here:
String s = "99"
assert 99 == Integer.parseInt(s)
Integer i = s as Integer
assert 99 == i
also you can make static import
import static java.lang.Integer.parseInt as asInteger
and after this use
String s = "99"
asInteger(s)
toInteger() method is available in groovy, you could use that.
Several ways to achieve this. Examples are as below
a. return "22".toInteger()
b. if("22".isInteger()) return "22".toInteger()
c. return "22" as Integer()
d. return Integer.parseInt("22")
Hope this helps
Groovy Style conversion:
Integer num = '589' as Integer
If you have request parameter:
Integer age = params.int('age')
def str = "32"
int num = str as Integer
Here is the an other way. if you don't like exceptions.
def strnumber = "100"
def intValue = strnumber.isInteger() ? (strnumber as int) : null
The way to use should still be the toInteger(), because it is not really deprecated.
int value = '99'.toInteger()
The String version is deprecated, but the CharSequence is an Interface that a String implements. So, using a String is ok, because your code will still works even when the method will only work with CharSequence. Same goes for isInteger()
See this question for reference :
How to convert a String to CharSequence?
I commented, because the notion of deprecated on this method got me confuse and I want to avoid that for other people.
The Simpler Way Of Converting A String To Integer In Groovy Is As Follows...
String aa="25"
int i= aa.toInteger()
Now "i" Holds The Integer Value.