Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #35711 > unrolled thread

Comparison structure?

Started byEric Douglas <e.d.programmer@gmail.com>
First post2016-10-04 07:25 -0700
Last post2016-10-05 22:41 +0200
Articles 15 — 7 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  Comparison structure? Eric Douglas <e.d.programmer@gmail.com> - 2016-10-04 07:25 -0700
    Re: Comparison structure? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-10-04 10:46 -0400
    Re: Comparison structure? Roedy Green <inquiry@mindprod.com> - 2016-10-04 09:53 -0700
      Re: Comparison structure? Eric Douglas <e.d.programmer@gmail.com> - 2016-10-04 10:29 -0700
        Re: Comparison structure? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-10-04 15:35 -0400
          Re: Comparison structure? Arne Vajhøj <arne@vajhoej.dk> - 2016-10-04 20:16 -0400
            Re: Comparison structure? Arne Vajhøj <arne@vajhoej.dk> - 2016-10-04 22:29 -0400
              Re: Comparison structure? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-10-05 08:08 -0400
                Re: Comparison structure? Arne Vajhøj <arne@vajhoej.dk> - 2016-10-05 20:27 -0400
    Re: Comparison structure? Martin Gregorie <martin@address-in-sig.invalid> - 2016-10-04 17:37 +0000
      Re: Comparison structure? Eric Douglas <e.d.programmer@gmail.com> - 2016-10-04 12:02 -0700
      Re: Comparison structure? j4n bur53 <janburse@fastmail.fm> - 2016-10-05 17:12 +0200
        Re: Comparison structure? j4n bur53 <janburse@fastmail.fm> - 2016-10-05 17:14 +0200
    Re: Comparison structure? Arne Vajhøj <arne@vajhoej.dk> - 2016-10-04 20:03 -0400
    Re: Comparison structure? Marcel Mueller <news.5.maazl@spamgourmet.org> - 2016-10-05 22:41 +0200

#35711 — Comparison structure?

FromEric Douglas <e.d.programmer@gmail.com>
Date2016-10-04 07:25 -0700
SubjectComparison structure?
Message-ID<59c17fe5-61a6-46dc-918f-ee5aa348e3fd@googlegroups.com>
I used some hard coded values to make a test block that compiles.  Suffice to say these are dynamically assigned.  The 3-way IF block sounds messy.  Is there a better structure?

          int compareMe = 1;
          int compareTo = 2;
          final int assignMe;
          if (compareMe == compareTo) {
               assignMe = 4;
          } else {
               if (compareMe > compareTo) {
                    assignMe = compareMe + 2;
               } else {
                    assignMe = compareMe;
               }
          }

[toc] | [next] | [standalone]


#35712

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2016-10-04 10:46 -0400
Message-ID<nt0fbh$qv2$1@dont-email.me>
In reply to#35711
On 10/4/2016 10:25 AM, Eric Douglas wrote:
> I used some hard coded values to make a test block that compiles.  Suffice to say these are dynamically assigned.  The 3-way IF block sounds messy.  Is there a better structure?
>
>           int compareMe = 1;
>           int compareTo = 2;
>           final int assignMe;
>           if (compareMe == compareTo) {
>                assignMe = 4;
>           } else {
>                if (compareMe > compareTo) {
>                     assignMe = compareMe + 2;
>                } else {
>                     assignMe = compareMe;
>                }
>           }

     You could rearrange it in many ways, but you're still stuck
with selecting among three distinct outcomes.  Therefore, at least
two tests are necessary.

     Some people frown on the ?: operator -- maybe they're just
grumpy by nature, I dunno -- but in situations of this kind I feel
it can reduce visual clutter and thereby improve readability.

	if (compareMe == compareTo) {
	    assignMe = 4;
	} else {
	    assignMe = compareMe + (compareMe > compareTo ? 2 : 0);
	}

Further condensation is certainly possible, but I'd likely not go there.

-- 
esosman@comcast-dot-net.invalid
The Tooth Fairy has gone high-tech, now pays in Bitecoin.

[toc] | [prev] | [next] | [standalone]


#35713

FromRoedy Green <inquiry@mindprod.com>
Date2016-10-04 09:53 -0700
Message-ID<vin7vbtorg7k171plq29ve3fo4fut237d5@4ax.com>
In reply to#35711
On Tue, 4 Oct 2016 07:25:22 -0700 (PDT), Eric Douglas
<e.d.programmer@gmail.com> wrote:

>Is there a better structure?
 the only alternative I can think of is to use a compare method that
returns +1 -1 0.
Then you could use a switch.

[toc] | [prev] | [next] | [standalone]


#35714

FromEric Douglas <e.d.programmer@gmail.com>
Date2016-10-04 10:29 -0700
Message-ID<cfb773de-671a-46e7-9d79-e821780c7bcb@googlegroups.com>
In reply to#35713
On Tuesday, October 4, 2016 at 12:53:51 PM UTC-4, Roedy Green wrote:
> >Is there a better structure?
>  the only alternative I can think of is to use a compare method that
> returns +1 -1 0.
> Then you could use a switch.

In that case you'd have to override the compareTo?
I read the doc on that method and it says returns a zero, or a value less than or greater than zero.  If it's not guaranteed to return specific values for less than or greater than, what would be the switch case?
This seems at least one reason people in the following thread suggest sticking with the 3-way if.
http://stackoverflow.com/questions/18510360/how-to-use-greater-than-or-equal-in-a-switch-statement

Otherwise that code would be equivalent to
          Integer compareMe = 1;
          int compareTo = 2;
          final int assignMe;
          switch (compareMe.compareTo(compareTo)) {
          case 0:
               assignMe = 4;
               break;
          case 1:
               assignMe = compareMe + 2;
               break;
          case -1:
               assignMe = compareMe;
               break;
          }

Of course Integer is final so you couldn't even just subclass it to override compareTo.  Without having 3 certain return values, this method ends up uglier.

[toc] | [prev] | [next] | [standalone]


#35717

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2016-10-04 15:35 -0400
Message-ID<nt109m$r82$1@dont-email.me>
In reply to#35714
On 10/4/2016 1:29 PM, Eric Douglas wrote:
> On Tuesday, October 4, 2016 at 12:53:51 PM UTC-4, Roedy Green wrote:
>>> Is there a better structure?
>>  the only alternative I can think of is to use a compare method that
>> returns +1 -1 0.
>> Then you could use a switch.
>
> In that case you'd have to override the compareTo?
> I read the doc on that method and it says returns a zero, or a value less than or greater than zero.  If it's not guaranteed to return specific values for less than or greater than, what would be the switch case?
> This seems at least one reason people in the following thread suggest sticking with the 3-way if.
> http://stackoverflow.com/questions/18510360/how-to-use-greater-than-or-equal-in-a-switch-statement
>
> Otherwise that code would be equivalent to
>           Integer compareMe = 1;
>           int compareTo = 2;
>           final int assignMe;
>           switch (compareMe.compareTo(compareTo)) {
>           case 0:
>                assignMe = 4;
>                break;
>           case 1:
>                assignMe = compareMe + 2;
>                break;
>           case -1:
>                assignMe = compareMe;
>                break;
>           }
>
> Of course Integer is final so you couldn't even just subclass it to override compareTo.  Without having 3 certain return values, this method ends up uglier.

     You could use some static methods of Integer to eliminate
the Integer object instances and fix the range problem:

	int compareMe = 1;
	int compareTo = 2;
	final int assignMe;
	switch(Integer.signum(Integer.compare(compareMe, compareTo))) {
	case 0:
	    assignMe = 4;
	    break;
	case 1:
	    assignMe = compareMe + 2;
	    break;
	default:  // not "case -1:"
	    assignMe = compareMe;
	    break;
	}

However, I'd be disinclined to call this an "improvement" over
the original code.

-- 
esosman@comcast-dot-net.invalid
The Tooth Fairy has gone high-tech, now pays in Bitecoin.

[toc] | [prev] | [next] | [standalone]


#35721

FromArne Vajhøj <arne@vajhoej.dk>
Date2016-10-04 20:16 -0400
Message-ID<nt1gom$thu$1@gioia.aioe.org>
In reply to#35717
On 10/4/2016 3:35 PM, Eric Sosman wrote:
> On 10/4/2016 1:29 PM, Eric Douglas wrote:
>> On Tuesday, October 4, 2016 at 12:53:51 PM UTC-4, Roedy Green wrote:
>>>> Is there a better structure?
>>>  the only alternative I can think of is to use a compare method that
>>> returns +1 -1 0.
>>> Then you could use a switch.
>>
>> In that case you'd have to override the compareTo?
>> I read the doc on that method and it says returns a zero, or a value
>> less than or greater than zero.  If it's not guaranteed to return
>> specific values for less than or greater than, what would be the
>> switch case?
>> This seems at least one reason people in the following thread suggest
>> sticking with the 3-way if.
>> http://stackoverflow.com/questions/18510360/how-to-use-greater-than-or-equal-in-a-switch-statement
>>
>>
>> Otherwise that code would be equivalent to
>>           Integer compareMe = 1;
>>           int compareTo = 2;
>>           final int assignMe;
>>           switch (compareMe.compareTo(compareTo)) {
>>           case 0:
>>                assignMe = 4;
>>                break;
>>           case 1:
>>                assignMe = compareMe + 2;
>>                break;
>>           case -1:
>>                assignMe = compareMe;
>>                break;
>>           }
>>
>> Of course Integer is final so you couldn't even just subclass it to
>> override compareTo.  Without having 3 certain return values, this
>> method ends up uglier.
>
>     You could use some static methods of Integer to eliminate
> the Integer object instances and fix the range problem:
>
>     int compareMe = 1;
>     int compareTo = 2;
>     final int assignMe;
>     switch(Integer.signum(Integer.compare(compareMe, compareTo))) {
>     case 0:
>         assignMe = 4;
>         break;
>     case 1:
>         assignMe = compareMe + 2;
>         break;
>     default:  // not "case -1:"
>         assignMe = compareMe;
>         break;
>     }
>
> However, I'd be disinclined to call this an "improvement" over
> the original code.

Well - if one is competing in a code obfuscation contest then I will 
suggest:

     int compareMe = 1;
     final int assignMe = cases[Integer.signum(compareMe - compareTo) + 
1].option(compareMe, compareTo);
     int compareTo = 2;

with:

	@FunctionalInterface
	private interface Case {
		public int option(int compareMe, int compareTo);
	}
	private static Case[] cases = { (me,to) -> me, (me,to) -> 4, (me,to) -> 
me + 2 };

:-)

Arne

[toc] | [prev] | [next] | [standalone]


#35722

FromArne Vajhøj <arne@vajhoej.dk>
Date2016-10-04 22:29 -0400
Message-ID<nt1oim$1646$1@gioia.aioe.org>
In reply to#35721
On 10/4/2016 8:16 PM, Arne Vajhøj wrote:
> Well - if one is competing in a code obfuscation contest then I will
> suggest:
>
>     int compareMe = 1;
>     final int assignMe = cases[Integer.signum(compareMe - compareTo) +
> 1].option(compareMe, compareTo);
>     int compareTo = 2;
>
> with:
>
>     @FunctionalInterface
>     private interface Case {
>         public int option(int compareMe, int compareTo);
>     }
>     private static Case[] cases = { (me,to) -> me, (me,to) -> 4, (me,to)
> -> me + 2 };
>
> :-)

Well - I think the concept can actually be twisted into something
that is almost readable!

     @FunctionalInterface
     private static interface Case {
         public int option(int compareMe, int compareTo);
     }

     public static abstract class Comparison {
         protected Case lt;
         protected Case eq;
         protected Case gt;
         private int compareMe;
         private int compareTo;
         public Comparison(int compareMe, int compareTo) {
             this.compareMe = compareMe;
             this.compareTo = compareTo;
         }
         public int execute() {
             switch(Integer.signum(compareMe - compareTo)) {
                 case -1:
                     return lt.option(compareMe, compareTo);
                 case 0:
                     return eq.option(compareMe, compareTo);
                 case 1:
                     return gt.option(compareMe, compareTo);
                 default:
                     throw new RuntimeException("Bye bye");
             }
         }
     }

     int compareMe = 1;
     int compareTo = 2;
     final int assignMe = new Comparison(compareMe, compareTo) {
             {
                 lt = (me,to) -> me;
                 eq = (me,to) -> 4;
                 gt = (me,to) -> me + 2;
             }
         }.execute();

Arne


[toc] | [prev] | [next] | [standalone]


#35724

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2016-10-05 08:08 -0400
Message-ID<nt2qg6$o96$1@dont-email.me>
In reply to#35722
On 10/4/2016 10:29 PM, Arne Vajhøj wrote:
>[...]
>         private int compareMe;
>         private int compareTo;
> [...]
>             switch(Integer.signum(compareMe - compareTo)) {

     Bad Arne!  B-A-A-D Arne!  Wear this dunce cap and sit in the corner!

     (Hint: Why do "sign-of-difference" and "comparison" sometimes
give different answers?)

     (Hint #2: compareMe = -100000, compareTo = 0x7fffffff)

-- 
esosman@comcast-dot-net.invalid
The Tooth Fairy has gone high-tech, now pays in Bitecoin.

[toc] | [prev] | [next] | [standalone]


#35731

FromArne Vajhøj <arne@vajhoej.dk>
Date2016-10-05 20:27 -0400
Message-ID<nt45q4$vuf$1@gioia.aioe.org>
In reply to#35724
On 10/5/2016 8:08 AM, Eric Sosman wrote:
> On 10/4/2016 10:29 PM, Arne Vajhøj wrote:
>> [...]
>>         private int compareMe;
>>         private int compareTo;
>> [...]
>>             switch(Integer.signum(compareMe - compareTo)) {
>
>     Bad Arne!  B-A-A-D Arne!  Wear this dunce cap and sit in the corner!
>
>     (Hint: Why do "sign-of-difference" and "comparison" sometimes
> give different answers?)
>
>     (Hint #2: compareMe = -100000, compareTo = 0x7fffffff)

OK. Integer.compare then.

Arne

[toc] | [prev] | [next] | [standalone]


#35715

FromMartin Gregorie <martin@address-in-sig.invalid>
Date2016-10-04 17:37 +0000
Message-ID<nt0pcj$r9u$1@dont-email.me>
In reply to#35711
On Tue, 04 Oct 2016 07:25:22 -0700, Eric Douglas wrote:

> I used some hard coded values to make a test block that compiles. 
> Suffice to say these are dynamically assigned.  The 3-way IF block
> sounds messy.  Is there a better structure?
> 
>           int compareMe = 1;
>           int compareTo = 2;
>           final int assignMe;
>           if (compareMe == compareTo) {
>                assignMe = 4;
>           } else {
>                if (compareMe > compareTo) {
>                     assignMe = compareMe + 2;
>                } else {
>                     assignMe = compareMe;
>                }
>           }
>
Three ways is always a bit of a toss-up because it looks messy any way 
you implement it. 

Personally, I think a switch is more readable: with four or more branches 
its the way to go but I might also use it for a three way branch, 
especially if each branch is only a few lines of inline code. 

I'd only ever assign constants to assignMe, preferably defining them as 
an enum list or a set of named integer constants. Using a mix of 
constants and calculated values is bound to trip a maintenance programmer 
at some point. 

You could also use an enum with class bodies. 


-- 
martin@   | Martin Gregorie
gregorie. | Essex, UK
org       |

[toc] | [prev] | [next] | [standalone]


#35716

FromEric Douglas <e.d.programmer@gmail.com>
Date2016-10-04 12:02 -0700
Message-ID<18de28f1-b2f2-4905-92db-1c5e3e6c4a5f@googlegroups.com>
In reply to#35715
On Tuesday, October 4, 2016 at 1:37:44 PM UTC-4, Martin Gregorie wrote:
> Three ways is always a bit of a toss-up because it looks messy any way 
> you implement it. 
> 
> Personally, I think a switch is more readable: with four or more branches 
> its the way to go but I might also use it for a three way branch, 
> especially if each branch is only a few lines of inline code. 
> 
> I'd only ever assign constants to assignMe, preferably defining them as 
> an enum list or a set of named integer constants. Using a mix of 
> constants and calculated values is bound to trip a maintenance programmer 
> at some point. 
> 
> You could also use an enum with class bodies. 

There are no constants in this example.  The 1, 2s, and 4 are there for show, so it compiles.  In the actual implementation those are all complex object.method() results. 

[toc] | [prev] | [next] | [standalone]


#35725

Fromj4n bur53 <janburse@fastmail.fm>
Date2016-10-05 17:12 +0200
Message-ID<nt358q$lld$1@news.albasani.net>
In reply to#35715
Martin Gregorie schrieb:
> Three ways is always a bit of a toss-up because it looks messy any way
> you implement it.

since JDK 1.7 there is the class Integer:

     public static int compare(int x, int y);

which avoids the boxing overhead.
the contract says <0, 0, >0,
but the implementation does -1,0,+1

(historically compare to could be implemented
by x-y, if |x| and |y| are less than 2^30,
because then the difference can be correctly
represented with the desired sign,

this works fine for byte, short and
char, if int widening is used, we therefore
find in JDK 1.7 in the corresponding wrapper
classes:

     public static int compare(byte x, byte y) {
         return x - y;
     }

     public static int compare(short x, short y) {
         return x - y;
     }

     public static int compare(char x, char y) {
         return x - y;
     }

but the exception is int, since for int
arguments the condition |x| and |y| are less
than 2^30, since the int range is one binary
magnitude bigger, similar problem with long:

     public static int compare(int x, int y) {
         return (x < y) ? -1 : ((x == y) ? 0 : 1);
     }

     public static int compare(long x, long y) {
         return (x < y) ? -1 : ((x == y) ? 0 : 1);
     }




[toc] | [prev] | [next] | [standalone]


#35726

Fromj4n bur53 <janburse@fastmail.fm>
Date2016-10-05 17:14 +0200
Message-ID<nt35c8$lld$2@news.albasani.net>
In reply to#35725
j4n bur53 schrieb:
> (historically compare to could be implemented
historically CPU CMP is just a SUB and checking some flags

[toc] | [prev] | [next] | [standalone]


#35720

FromArne Vajhøj <arne@vajhoej.dk>
Date2016-10-04 20:03 -0400
Message-ID<nt1g10$snf$1@gioia.aioe.org>
In reply to#35711
On 10/4/2016 10:25 AM, Eric Douglas wrote:
> I used some hard coded values to make a test block that compiles.
> Suffice to say these are dynamically assigned. The 3-way IF block sounds
> messy. Is there a better structure?
>
>           int compareMe = 1;
>           int compareTo = 2;
>           final int assignMe;
>           if (compareMe == compareTo) {
>                assignMe = 4;
>           } else {
>                if (compareMe > compareTo) {
>                     assignMe = compareMe + 2;
>                } else {
>                     assignMe = compareMe;
>                }
>           }

It is all about readability.

That code is very readable. The reader easily understand
what the code does. Good code in my opinion.

I would flatten it like:

         int compareMe = 1;
         int compareTo = 2;
         final int assignMe;
         if (compareMe == compareTo) {
              assignMe = 4;
         } else if (compareMe > compareTo) {
              assignMe = compareMe + 2;
         } else {
              assignMe = compareMe;
         }

but that is just a minor change.

Arne

[toc] | [prev] | [next] | [standalone]


#35727

FromMarcel Mueller <news.5.maazl@spamgourmet.org>
Date2016-10-05 22:41 +0200
Message-ID<nt3oi7$ihi$1@gwaiyur.mb-net.net>
In reply to#35711
On 04.10.16 16.25, Eric Douglas wrote:
> I used some hard coded values to make a test block that compiles.  Suffice to say these are dynamically assigned.  The 3-way IF block sounds messy.  Is there a better structure?
>
>            int compareMe = 1;
>            int compareTo = 2;
>            final int assignMe;
>            if (compareMe == compareTo) {
>                 assignMe = 4;
>            } else {
>                 if (compareMe > compareTo) {
>                      assignMe = compareMe + 2;
>                 } else {
>                      assignMe = compareMe;
>                 }
>            }

This is a common pattern and I do not know any significantly better 
solution than this.
I would only omit the first else brace to clarify that all three paths 
are at the same level.

if (compareMe == compareTo) {
     assignMe = 4;
} else if (compareMe > compareTo) {
     assignMe = compareMe + 2;
} else {
     assignMe = compareMe;
}


Marcel

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.java.programmer


csiph-web