Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Subtracting unsigned entities

Reply
Thread Tools

Subtracting unsigned entities

 
 
fred.l.kleinschmidt@boeing.com
Guest
Posts: n/a
 
      05-12-2008
If one knows that x and y are unsigned integers (of unknown size -
they may be short, int, long, long long), what is the most portable
way to determine their difference?

If x is smaller than y, then x-y is negative.

A naive approach is
if ( x > y ) {
...
}

but a compiler may code (x>y) as (x-y > 0).

--
Fred Kleinschmidt
Boeing Aero C&S
 
Reply With Quote
 
 
 
 
Ben Pfaff
Guest
Posts: n/a
 
      05-12-2008
writes:

> If one knows that x and y are unsigned integers (of unknown size -
> they may be short, int, long, long long), what is the most portable
> way to determine their difference?
>
> If x is smaller than y, then x-y is negative.


Mathematically, yes. But in C, the difference of two values of
type unsigned int is always nonnegative.

> A naive approach is
> if ( x > y ) {
> ...
> }
>
> but a compiler may code (x>y) as (x-y > 0).


No, the compiler is obliged to produce the correct result.
--
"The way I see it, an intelligent person who disagrees with me is
probably the most important person I'll interact with on any given
day."
--Billy Chambless
 
Reply With Quote
 
 
 
 
Tomás Ó hÉilidhe
Guest
Posts: n/a
 
      05-12-2008
On May 12, 11:18*pm, fred.l.kleinschm...@boeing.com wrote:
> If one knows that x and y are unsigned integers (of unknown size -
> they may be short, int, long, long long), what is the most portable
> way to determine their difference?



Let's take an example:

unsigned x, y;

x = 65530u;
y = 655u;

The difference between these two is 64875.

If you do (x-y), you'll get 64875u. However if you do (y-x), you'll
get an implementation-defined value which depends on the value of
UINT_MAX (because when you go past zero you'll start counting backward
from UINT_MAX).


> If x is smaller than y, then x-y is negative.
>
> A naive approach is
> * *if ( x > y ) {
> * * * ...
> * *}
>
> but a compiler may code (x>y) as *(x-y > 0)



The if method is the only one that comes to mind.


 
Reply With Quote
 
Bart
Guest
Posts: n/a
 
      05-12-2008
On May 12, 11:18*pm, fred.l.kleinschm...@boeing.com wrote:
> If one knows that x and y are unsigned integers (of unknown size -
> they may be short, int, long, long long), what is the most portable
> way to determine their difference?
>
> If x is smaller than y, then x-y is negative.
>
> A naive approach is
> * *if ( x > y ) {
> * * * ...
> * *}
>
> but a compiler may code (x>y) as *(x-y > 0).


What do you mean by difference?

If you mean x-y, then this will give strange results when x<y (it
can't be negative).

If you mean max(x,y)-min(x,y) then your 'naive' approach will likely
work well.

--
Bartc
 
Reply With Quote
 
Peter Nilsson
Guest
Posts: n/a
 
      05-13-2008
Bart wrote:
> fred.l.kleinschm...@boeing.com wrote:
> > If one knows that x and y are unsigned integers (of unknown
> > size - they may be short, int, long, long long), what is the
> > most portable way to determine their difference?


Subtraction. Though that need not be the minimum 'distance'
metric.

> > If x is smaller than y, then x-y is negative.
> >
> > A naive approach is
> > if ( x > y ) {
> > ...
> > }
> >
> > but a compiler may code (x>y) as (x-y > 0).

>
> What do you mean by difference?
>
> If you mean x-y, then this will give strange results when x<y (it
> can't be negative).


It can in some circumstances, e.g. USHRT_MAX < INT_MAX.

--
Peter
 
Reply With Quote
 
Chris Dollin
Guest
Posts: n/a
 
      05-13-2008
wrote:

> If one knows that x and y are unsigned integers (of unknown size -
> they may be short, int, long, long long), what is the most portable
> way to determine their difference?
>
> If x is smaller than y, then x-y is negative.
>
> A naive approach is
> if ( x > y ) {
> ...
> }
>
> but a compiler may code (x>y) as (x-y > 0).


It might code it as `x + 17`, too, but if it wants to be correct
both decisions would be suspect.

--
"Why, /yes/, madame. Certainly. Now?" - Lois McMaster Bujold /A Civil Campaign/

Hewlett-Packard Limited Cain Road, Bracknell, registered no:
registered office: Berks RG12 1HN 690597 England

 
Reply With Quote
 
fred.l.kleinschmidt@boeing.com
Guest
Posts: n/a
 
      05-13-2008
On May 12, 3:58*pm, Bart <b...@freeuk.com> wrote:
> On May 12, 11:18*pm, fred.l.kleinschm...@boeing.com wrote:
>
> > If one knows that x and y are unsigned integers (of unknown size -
> > they may be short, int, long, long long), what is the most portable
> > way to determine their difference?

>
> > If x is smaller than y, then x-y is negative.

>
> > A naive approach is
> > * *if ( x > y ) {
> > * * * ...
> > * *}

>
> > but a compiler may code (x>y) as *(x-y > 0).

>
> What do you mean by difference?
>
> If you mean x-y, then this will give strange results when x<y (it
> can't be negative).
>
> If you mean max(x,y)-min(x,y) then your 'naive' approach will likely
> work well.
>


The problem came up on a Unix platform, where some code was trying
to check for a double-click. Each time button1 is clicked, it checks
the time with the previous time it was clicked; if the difference is
small enough, a double-click is assumed.

The times are stored in a variable of type Time, defined as
an unsigned int on some platforms, unsigned long on others, storing
clock time in milliseconds.

For an unsigned int, the value will wrap every 47 days. The original
code was

if ( (newtime - oldtime) < doubleclicktime ) {
/* perform double-click action */
}

That code is unsafe: as oldtime approaches UINT_MAX, the risk
is that newtime might occur after time wraps, thus might be
a small integer, and (newtime - oldtime) is mathematically
negative.

Since others have said that the compiler is obliged to
perform the if-test properly, my solution is

if ( t2 > t1 ) {
delta = t2 - t1;
}
else {
delta = (UINT_MAX - t1) + t2 + 1;
}

--
Fred Kleinschmidt

 
Reply With Quote
 
Chris Dollin
Guest
Posts: n/a
 
      05-13-2008
wrote:

> Since others have said that the compiler is obliged to
> perform the if-test properly, my solution is
>
> if ( t2 > t1 ) {
> delta = t2 - t1;
> }
> else {
> delta = (UINT_MAX - t1) + t2 + 1;
> }


Not
if (t2 > t1) delta = t2 - t1;
else delta = t1 - t2;

? Because that seems simpler and at least as correct.

(Of course I'd write it as

delta = t2 > t1 ? t2 - t1 : t1 - t2;

)

--
/Questions? Answers! Answers? Questions!/ - Focus

Hewlett-Packard Limited registered office: Cain Road, Bracknell,
registered no: 690597 England Berks RG12 1HN

 
Reply With Quote
 
Øyvind Røtvold
Guest
Posts: n/a
 
      05-13-2008
writes:

> On May 12, 3:58*pm, Bart <b...@freeuk.com> wrote:

[ snip ]
> For an unsigned int, the value will wrap every 47 days. The original
> code was
>
> if ( (newtime - oldtime) < doubleclicktime ) {
> /* perform double-click action */
> }
>
> That code is unsafe:


No.

> as oldtime approaches UINT_MAX, the risk
> is that newtime might occur after time wraps, thus might be
> a small integer,


Yes.

> and (newtime - oldtime) is mathematically negative.


If newtime and oldtime are of the same unsigned type, the result will
never be negative, and (newtime - oldtime) will be the correct time
difference even when there's a wrap. Assuming ofcourse that the timer
wraps correctly, this will work in any kind of modulo arithmetic.
Whoever made this code originally probably knew what he was doing.

[ snip ]

--
... __o Øyvind
... _`\(, http://www.darkside.no/olr/
... (_)/(_) ... biciclare necesse est ...
 
Reply With Quote
 
Harald van Dijk
Guest
Posts: n/a
 
      05-13-2008
On Tue, 13 May 2008 22:55:41 +0200, Øyvind Røtvold wrote:
> writes:
>> On May 12, 3:58Â*pm, Bart <b...@freeuk.com> wrote:

> [ snip ]
>> For an unsigned int, the value will wrap every 47 days. The original
>> code was
>>
>> if ( (newtime - oldtime) < doubleclicktime ) {
>> /* perform double-click action */
>> }
>>
>> That code is unsafe:

>
> No.
>
>> as oldtime approaches UINT_MAX, the risk is that newtime might occur
>> after time wraps, thus might be a small integer,

>
> Yes.
>
>> and (newtime - oldtime) is mathematically negative.

>
> If newtime and oldtime are of the same unsigned type, the result will
> never be negative, and (newtime - oldtime) will be the correct time
> difference even when there's a wrap.


If newtime and oldtime are of the same unsigned type, *and that unsigned
type is unsigned int or wider*, then yes. It is unsigned int here,
apparently, so then it is safe, but it's not safe with smaller unsigned
types. If they were of type unsigned short, for example, it's very well
possible for newtime - oldtime to produce a negative result, because
newtime and oldtime will be promoted, typically to signed int, before any
subtraction takes place.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Subtracting two big unsigned numbers Keith Thompson C Programming 4 06-14-2011 11:58 PM
Re: Subtracting two big unsigned numbers Thomas Richter C Programming 2 06-11-2011 03:02 AM
(int) -> (unsigned) -> (int) or (unsigned) -> (int) -> (unsigned):I'll loose something? pozz C Programming 12 03-20-2011 11:32 PM
Subtracting unsigned ints bg_ie@yahoo.com C Programming 10 06-20-2006 11:22 AM
HTML::Entities::encode() returning wrong(?) entities Jim Higson Perl Misc 3 07-25-2004 09:13 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57