Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #39589 > unrolled thread
| Started by | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| First post | 2020-07-29 17:19 +0200 |
| Last post | 2020-07-29 20:59 +0200 |
| Articles | 15 — 5 participants |
Back to article view | Back to comp.lang.java.programmer
Compare generics (that are numbers) Cecil Westerhof <Cecil@decebal.nl> - 2020-07-29 17:19 +0200
Re: Compare generics (that are numbers) Arne Vajhøj <arne@vajhoej.dk> - 2020-07-29 13:21 -0400
Re: Compare generics (that are numbers) Arne Vajhøj <arne@vajhoej.dk> - 2020-07-29 13:27 -0400
Re: Compare generics (that are numbers) Eric Sosman <esosman@comcast-dot-net.invalid> - 2020-07-29 13:48 -0400
Re: Compare generics (that are numbers) Cecil Westerhof <Cecil@decebal.nl> - 2020-07-29 20:42 +0200
Re: Compare generics (that are numbers) Arne Vajhøj <arne@vajhoej.dk> - 2020-07-29 14:50 -0400
Re: Compare generics (that are numbers) Cecil Westerhof <Cecil@decebal.nl> - 2020-07-29 21:53 +0200
Re: Compare generics (that are numbers) Arne Vajhøj <arne@vajhoej.dk> - 2020-07-29 21:32 -0400
Re: Compare generics (that are numbers) Cecil Westerhof <Cecil@decebal.nl> - 2020-07-30 11:33 +0200
Re: Compare generics (that are numbers) Eric Sosman <esosman@comcast-dot-net.invalid> - 2020-07-30 09:03 -0400
Re: Compare generics (that are numbers) Cecil Westerhof <Cecil@decebal.nl> - 2020-07-30 17:00 +0200
Re: Compare generics (that are numbers) Arne Vajhøj <arne@vajhoej.dk> - 2020-07-30 09:21 -0400
Re: Compare generics (that are numbers) Silvio <silvio@internet.com> - 2020-07-30 08:51 +0200
Re: Compare generics (that are numbers) Cecil Westerhof <Cecil@decebal.nl> - 2020-07-30 11:36 +0200
Re: Compare generics (that are numbers) Marcel Mueller <news.5.maazl@spamgourmet.org> - 2020-07-29 20:59 +0200
| From | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| Date | 2020-07-29 17:19 +0200 |
| Subject | Compare generics (that are numbers) |
| Message-ID | <87k0ym73id.fsf@munus.decebal.nl> |
I have a class that starts with:
abstract class CalcValuesGeneric<E> {
E will be Integer, int, Float or float. (For now, but always a Number.)
What is the best way to determine which of the two is lower?
--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
[toc] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2020-07-29 13:21 -0400 |
| Message-ID | <rfsb7k$4gr$1@gioia.aioe.org> |
| In reply to | #39589 |
On 7/29/2020 11:19 AM, Cecil Westerhof wrote:
> I have a class that starts with:
> abstract class CalcValuesGeneric<E> {
>
> E will be Integer, int, Float or float. (For now, but always a Number.)
> What is the best way to determine which of the two is lower?
T extends Number?
Example:
public class NumFun {
public static class Demo<T extends Number> {
public boolean gt(T a, T b) {
return a.doubleValue() > b.doubleValue();
}
}
public static void main(String[] args) {
Demo<Double> dd = new Demo<>();
System.out.println(dd.gt(1.0, 0.0));
System.out.println(dd.gt(1.0, 1.0));
System.out.println(dd.gt(0.0, 1.0));
Demo<Integer> di = new Demo<>();
System.out.println(di.gt(1, 0));
System.out.println(di.gt(1, 1));
System.out.println(di.gt(0, 1));
}
}
Arne
[toc] | [prev] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2020-07-29 13:27 -0400 |
| Message-ID | <rfsbik$8v6$1@gioia.aioe.org> |
| In reply to | #39590 |
On 7/29/2020 1:21 PM, Arne Vajhøj wrote:
> On 7/29/2020 11:19 AM, Cecil Westerhof wrote:
>> I have a class that starts with:
>> abstract class CalcValuesGeneric<E> {
>>
>> E will be Integer, int, Float or float. (For now, but always a Number.)
>> What is the best way to determine which of the two is lower?
>
> T extends Number?
>
> Example:
>
> public class NumFun {
> public static class Demo<T extends Number> {
> public boolean gt(T a, T b) {
> return a.doubleValue() > b.doubleValue();
> }
> }
> public static void main(String[] args) {
> Demo<Double> dd = new Demo<>();
> System.out.println(dd.gt(1.0, 0.0));
> System.out.println(dd.gt(1.0, 1.0));
> System.out.println(dd.gt(0.0, 1.0));
> Demo<Integer> di = new Demo<>();
> System.out.println(di.gt(1, 0));
> System.out.println(di.gt(1, 1));
> System.out.println(di.gt(0, 1));
> }
> }
Note that there are some bad corner cases for long/Long.
Arne
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2020-07-29 13:48 -0400 |
| Message-ID | <rfscpe$doa$1@dont-email.me> |
| In reply to | #39589 |
On 7/29/2020 11:19 AM, Cecil Westerhof wrote:
> I have a class that starts with:
> abstract class CalcValuesGeneric<E> {
>
> E will be Integer, int, Float or float. (For now, but always a Number.)
> What is the best way to determine which of the two is lower?
Aside: How can you get `<E>' to be `<int>' or `<float>'? Is that
something new? I'm still on Java 8, but the JLS for 14 says "Seq<int>
is illegal, as primitive types cannot be type arguments." (4.5)
Anyhow, could you use `CalcValueGeneric<E extends Comparable<E>>'
(double-check my syntax)? That would at least handle Integer/Integer
and Float/Float, though it wouldn't help with Integer/Float.
--
esosman@comcast-dot-net.invalid
Donald Trump is a self-mad man.
One hundred seventy-five days to go.
[toc] | [prev] | [next] | [standalone]
| From | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| Date | 2020-07-29 20:42 +0200 |
| Message-ID | <87ft9a6u35.fsf@munus.decebal.nl> |
| In reply to | #39592 |
Eric Sosman <esosman@comcast-dot-net.invalid> writes:
> On 7/29/2020 11:19 AM, Cecil Westerhof wrote:
>> I have a class that starts with:
>> abstract class CalcValuesGeneric<E> {
>>
>> E will be Integer, int, Float or float. (For now, but always a Number.)
>> What is the best way to determine which of the two is lower?
>
> Aside: How can you get `<E>' to be `<int>' or `<float>'? Is that
> something new? I'm still on Java 8, but the JLS for 14 says "Seq<int>
> is illegal, as primitive types cannot be type arguments." (4.5)
You are completely right, I was not thinking straight. :'-(
--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
[toc] | [prev] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2020-07-29 14:50 -0400 |
| Message-ID | <rfsgek$jm4$1@gioia.aioe.org> |
| In reply to | #39593 |
On 7/29/2020 2:42 PM, Cecil Westerhof wrote:
> Eric Sosman <esosman@comcast-dot-net.invalid> writes:
>> On 7/29/2020 11:19 AM, Cecil Westerhof wrote:
>>> I have a class that starts with:
>>> abstract class CalcValuesGeneric<E> {
>>>
>>> E will be Integer, int, Float or float. (For now, but always a Number.)
>>> What is the best way to determine which of the two is lower?
>>
>> Aside: How can you get `<E>' to be `<int>' or `<float>'? Is that
>> something new? I'm still on Java 8, but the JLS for 14 says "Seq<int>
>> is illegal, as primitive types cannot be type arguments." (4.5)
>
> You are completely right, I was not thinking straight. :'-(
Probably a common miswording.
class CalcValuesGeneric<E> {
void something(E v)
...
cvg.something(x);
E can be Integer or Float but not int or float.
But x can be int and float as well due to auto boxing.
Arne
[toc] | [prev] | [next] | [standalone]
| From | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| Date | 2020-07-29 21:53 +0200 |
| Message-ID | <87bljy6qu3.fsf@munus.decebal.nl> |
| In reply to | #39594 |
Arne Vajhøj <arne@vajhoej.dk> writes:
> On 7/29/2020 2:42 PM, Cecil Westerhof wrote:
>> Eric Sosman <esosman@comcast-dot-net.invalid> writes:
>>> On 7/29/2020 11:19 AM, Cecil Westerhof wrote:
>>>> I have a class that starts with:
>>>> abstract class CalcValuesGeneric<E> {
>>>>
>>>> E will be Integer, int, Float or float. (For now, but always a Number.)
>>>> What is the best way to determine which of the two is lower?
>>>
>>> Aside: How can you get `<E>' to be `<int>' or `<float>'? Is that
>>> something new? I'm still on Java 8, but the JLS for 14 says "Seq<int>
>>> is illegal, as primitive types cannot be type arguments." (4.5)
>>
>> You are completely right, I was not thinking straight. :'-(
>
> Probably a common miswording.
>
> class CalcValuesGeneric<E> {
> void something(E v)
> ...
> cvg.something(x);
>
> E can be Integer or Float but not int or float.
>
> But x can be int and float as well due to auto boxing.
But I do not want auto boxing. The particular case I am working with
shows that int can take 40% less CPU and memory when using Integer.
I will find another way. Thanks.
--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
[toc] | [prev] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2020-07-29 21:32 -0400 |
| Message-ID | <rft7um$17k2$1@gioia.aioe.org> |
| In reply to | #39596 |
On 7/29/2020 3:53 PM, Cecil Westerhof wrote:
> Arne Vajhøj <arne@vajhoej.dk> writes:
>> On 7/29/2020 2:42 PM, Cecil Westerhof wrote:
>>> Eric Sosman <esosman@comcast-dot-net.invalid> writes:
>>>> On 7/29/2020 11:19 AM, Cecil Westerhof wrote:
>>>>> I have a class that starts with:
>>>>> abstract class CalcValuesGeneric<E> {
>>>>>
>>>>> E will be Integer, int, Float or float. (For now, but always a Number.)
>>>>> What is the best way to determine which of the two is lower?
>>>>
>>>> Aside: How can you get `<E>' to be `<int>' or `<float>'? Is that
>>>> something new? I'm still on Java 8, but the JLS for 14 says "Seq<int>
>>>> is illegal, as primitive types cannot be type arguments." (4.5)
>>>
>>> You are completely right, I was not thinking straight. :'-(
>>
>> Probably a common miswording.
>>
>> class CalcValuesGeneric<E> {
>> void something(E v)
>> ...
>> cvg.something(x);
>>
>> E can be Integer or Float but not int or float.
>>
>> But x can be int and float as well due to auto boxing.
>
> But I do not want auto boxing. The particular case I am working with
> shows that int can take 40% less CPU and memory when using Integer.
>
> I will find another way. Thanks.
Well - code that handle objects does require objects.
:-)
But if this is performance critical then why not just drop the
generic stuff and write specific code for the types?
Arne
[toc] | [prev] | [next] | [standalone]
| From | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| Date | 2020-07-30 11:33 +0200 |
| Message-ID | <87zh7h5ouj.fsf@munus.decebal.nl> |
| In reply to | #39597 |
Arne Vajhøj <arne@vajhoej.dk> writes: > But if this is performance critical then why not just drop the > generic stuff and write specific code for the types? Because I want to show the differences between using Float/float/Integer/int and different implementations thereof. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2020-07-30 09:03 -0400 |
| Message-ID | <rfugel$qk$1@dont-email.me> |
| In reply to | #39600 |
On 7/30/2020 5:33 AM, Cecil Westerhof wrote:
> Arne Vajhøj <arne@vajhoej.dk> writes:
>
>> But if this is performance critical then why not just drop the
>> generic stuff and write specific code for the types?
>
> Because I want to show the differences between using
> Float/float/Integer/int and different implementations thereof.
Is this a "practical problem," or a "teaching exercise?" If the
former, I'd be interested to know how it arises -- needing to compare
one arbitrary Number to another (BigDecimal vs. AtomicLong?) seems not
out of the question, but surely unusual.
If it's a teaching tool, you might want to reconsider the vehicle.
As has been pointed out, some combinations (DoubleAdder vs. BigInteger,
others) raise a lot of thorny and niggling special cases that might
tend to obscure whatever point you're trying to put across. Maybe if
folks had a better idea of the goals they'd suggest better approaches.
--
esosman@comcast-dot-net.invalid
If he's so rich, why ain't he smart?
One hundred seventy-four days to go.
[toc] | [prev] | [next] | [standalone]
| From | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| Date | 2020-07-30 17:00 +0200 |
| Message-ID | <87mu3h59qc.fsf@munus.decebal.nl> |
| In reply to | #39601 |
Eric Sosman <esosman@comcast-dot-net.invalid> writes: > On 7/30/2020 5:33 AM, Cecil Westerhof wrote: >> Arne Vajhøj <arne@vajhoej.dk> writes: >> >>> But if this is performance critical then why not just drop the >>> generic stuff and write specific code for the types? >> >> Because I want to show the differences between using >> Float/float/Integer/int and different implementations thereof. > > Is this a "practical problem," or a "teaching exercise?" If the > former, I'd be interested to know how it arises -- needing to compare > one arbitrary Number to another (BigDecimal vs. AtomicLong?) seems not > out of the question, but surely unusual. Lets lift a corner of the veil. ;-) It is in between. During a whiteboard session during a job interview I was asked to optimise something. It started with going from Float to Integer. (In this case that was possible.) The functionality of Integer was not used, so it was good to switch to int. But a further optimisation would be to use an int array. When back home I was curious and started implementing it. For readability I also tried int[number][2], but that did not work at all. I kept it in my program, because it is good to show the result in my opinion. Then I also tried int[2][number]. With 25 million records and 250 repeats I got: |-----------------------+--------+----------+---------+---------+---------+----------+----------+----------| | Type | Memory | Sys Time | Gen Min | Gen Max | Gen Avg | Calc Min | Calc Max | Calc Avg | |-----------------------+--------+----------+---------+---------+---------+----------+----------+----------| | Integer Class[number] | 3.8 GB | 34.0 | 5.33E3 | 1.11E4 | 7.65E3 | 367 | 656 | 447.60 | | int Class[number] | 2.3 GB | 15.5 | 2.53E3 | 4.64E3 | 3.44E3 | 202 | 340 | 267.40 | | int [2 * number] | 0.6 GB | 5.5 | 1.09E3 | 1.52E3 | 1.27E3 | 61 | 112 | 75.10 | | int [number][2] | 2.3 GB | 24.0 | 4.23E3 | 7.30E3 | 5.51E3 | 183 | 338 | 239.18 | | int [2][number] | 0.6 GB | 6.0 | 1.06E3 | 1.61E3 | 1.30E3 | 81 | 133 | 107.03 | |-----------------------+--------+----------+---------+---------+---------+----------+----------+----------| System time is in minutes. Other times in milliseconds. With Floats the savings on memory will be a lot less, because the overhead for objects is less. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof
[toc] | [prev] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2020-07-30 09:21 -0400 |
| Message-ID | <rfuhhc$q7p$1@gioia.aioe.org> |
| In reply to | #39600 |
On 7/30/2020 5:33 AM, Cecil Westerhof wrote: > Arne Vajhøj <arne@vajhoej.dk> writes: >> But if this is performance critical then why not just drop the >> generic stuff and write specific code for the types? > > Because I want to show the differences between using > Float/float/Integer/int and different implementations thereof. Then 40% difference proves the point. Arne
[toc] | [prev] | [next] | [standalone]
| From | Silvio <silvio@internet.com> |
|---|---|
| Date | 2020-07-30 08:51 +0200 |
| Message-ID | <5f226e02$0$14413$e4fe514c@newszilla.xs4all.nl> |
| In reply to | #39596 |
On 7/29/20 9:53 PM, Cecil Westerhof wrote:
> Arne Vajhøj <arne@vajhoej.dk> writes:
>
>> On 7/29/2020 2:42 PM, Cecil Westerhof wrote:
>>> Eric Sosman <esosman@comcast-dot-net.invalid> writes:
>>>> On 7/29/2020 11:19 AM, Cecil Westerhof wrote:
>>>>> I have a class that starts with:
>>>>> abstract class CalcValuesGeneric<E> {
>>>>>
>>>>> E will be Integer, int, Float or float. (For now, but always a Number.)
>>>>> What is the best way to determine which of the two is lower?
>>>>
>>>> Aside: How can you get `<E>' to be `<int>' or `<float>'? Is that
>>>> something new? I'm still on Java 8, but the JLS for 14 says "Seq<int>
>>>> is illegal, as primitive types cannot be type arguments." (4.5)
>>>
>>> You are completely right, I was not thinking straight. :'-(
>>
>> Probably a common miswording.
>>
>> class CalcValuesGeneric<E> {
>> void something(E v)
>> ...
>> cvg.something(x);
>>
>> E can be Integer or Float but not int or float.
>>
>> But x can be int and float as well due to auto boxing.
>
> But I do not want auto boxing. The particular case I am working with
> shows that int can take 40% less CPU and memory when using Integer.
>
> I will find another way. Thanks.
>
You could try Scala. It has type specialization that allows you to
prevent boxing overhead when using generics with primitive type parameters.
[toc] | [prev] | [next] | [standalone]
| From | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| Date | 2020-07-30 11:36 +0200 |
| Message-ID | <87v9i55opx.fsf@munus.decebal.nl> |
| In reply to | #39598 |
Silvio <silvio@internet.com> writes: > You could try Scala. It has type specialization that allows you to > prevent boxing overhead when using generics with primitive type > parameters. Is a possibility, but I think it better to do in Java. There is the possibility that someone that only uses Java will not be convinced by Scala code. I think I can manage in Java, but otherwise I can bring your tip into practice. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof
[toc] | [prev] | [next] | [standalone]
| From | Marcel Mueller <news.5.maazl@spamgourmet.org> |
|---|---|
| Date | 2020-07-29 20:59 +0200 |
| Message-ID | <rfsgu9$lpn$1@gwaiyur.mb-net.net> |
| In reply to | #39589 |
Am 29.07.20 um 17:19 schrieb Cecil Westerhof:
> I have a class that starts with:
> abstract class CalcValuesGeneric<E> {
>
> E will be Integer, int, Float or float. (For now, but always a Number.)
Java generics can never hold primitive types. This is prohibited by type
erasure. However autoboxing may apply.
> What is the best way to determine which of the two is lower?
A custom comparer which takes two arguments of type Number.
Note that this is a multiple dispatch problem since the value domains of
the different numeric types are not supersets of each other. No number
type can hold all values of all number types. I.e. the compare function
depends on both argument types not just a single type like virtual
functions.
I.e. to compare Double against BigInteger you cannot convert one
argument to the domain of the other one because this may cause either an
exception or loss of precision. Both prohibit the correct comparison result.
Even Integer vs. Float is not possible directly. In this special case
you may convert both values to double, because its value domain is a
superset of both types.
But considering Long vs. Double there is no type that can hold both
value domains. So you need to check first whether the Double is outside
the domain of Long (including not finite). In this case the result
depends only on the sing on the Double. At next you need to round the
Double down to the next whole number (floor) and convert it to long. In
case the result compares equal you need to check whether the rounded
Double value still equals the original and if not the Double was greater.
Also note that comparison against NaN values always return false except
for NaN != NaN. I.e. a < b is not equivalent with !(a >= b).
Since Java does not support multiple dispatch out of the box you need to
implement your own dispatch logic. The number of entries grows
quadratically with the number of types you want to support. E.g.
AtomicLong or BigInteger are additional types that might occur if you
restrict the generic type to Number.
Marcel
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.java.programmer
csiph-web