Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Rounding

2 views
Skip to first unread message

Russell Shaw

unread,
Jul 12, 2010, 4:58:41 AM7/12/10
to
Hi,
I want to round a number, y, to the largest multiple of h that is
less than y. Can i do:

int y = 27;
int h = 10;

y = y/h*h;

should give 20, or will compiler optimization cancel out h?

Vincenzo Mercuri

unread,
Jul 12, 2010, 5:42:03 AM7/12/10
to
Russell Shaw ha scritto:

Hi,
I think it will work fine since y/h*h means (y/h)*h
and the operator / will drop the fractional part of divisions
between integers. Just be careful of checking the case of h==0
if you are going to use that expression as a general formula.

--
Vincenzo Mercuri

Francois Grieu

unread,
Jul 12, 2010, 6:07:23 AM7/12/10
to

It will do what you want. The compiler is not free to make
optimizations that change the result of integer expressions.

Notice that for y = -27, you could get either -30 or -20.
That's another reason to use unsigned.

Other strictly equivalent options:
y = y-y%h;
y -= y%h;

If y is non-negative and h a power of two, there is also
y &= ~(h-1);

Francois Grieu

Vincenzo Mercuri

unread,
Jul 12, 2010, 6:30:01 AM7/12/10
to
Francois Grieu ha scritto:

> On 12/07/2010 10:58, Russell Shaw wrote:
>> I want to round a number, y, to the largest multiple of h that is
>> less than y. Can i do:
>>
>> int y = 27;
>> int h = 10;
>>
>> y = y/h*h;
>>
>> should give 20, or will compiler optimization cancel out h?
>
> It will do what you want. The compiler is not free to make
> optimizations that change the result of integer expressions.
>
> Notice that for y = -27, you could get either -30 or -20.

Yes, this is right for C90. Nevertheless compiling under C99
mode, you will always get -20


--
Vincenzo Mercuri

Richard Heathfield

unread,
Jul 12, 2010, 12:26:50 PM7/12/10
to

Multiplication and division associate left to right, so the compiler
can't optimise out the division - it must give the result 20 for the
above calculation.

Unfortunately, if you mean precisely what you say, y = y / h * h breaks
when y is an exact multiple of h. Say y = 27 and h = 9 - your calc gives
27, which isn't less than y's original value. It is quite possible, even
likely, that that's what you really meant. But, if you really meant that
you want to have the largest multiple of h that is *less than* y (not
less than or equal to y), you can do this instead:

y = ((y + h - 1) / h - 1) * h;

Beware overflow issues when using signed types. Also beware of negative
numbers - I haven't actually checked that the above will work with
negatives, and in fact it probably won't.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within

Vincenzo Mercuri

unread,
Jul 12, 2010, 1:54:14 PM7/12/10
to
Richard Heathfield ha scritto:

> Russell Shaw wrote:
>> Hi,
>> I want to round a number, y, to the largest multiple of h that is
>> less than y. Can i do:
>>
>> int y = 27;
>> int h = 10;
>>
>> y = y/h*h;
>>
>> should give 20, or will compiler optimization cancel out h?
>
> Multiplication and division associate left to right, so the compiler
> can't optimise out the division - it must give the result 20 for the
> above calculation.
>
> Unfortunately, if you mean precisely what you say, y = y / h * h breaks
> when y is an exact multiple of h. Say y = 27 and h = 9 - your calc gives
> 27, which isn't less than y's original value. It is quite possible, even
> likely, that that's what you really meant. But, if you really meant that
> you want to have the largest multiple of h that is *less than* y (not
> less than or equal to y), you can do this instead:
>
> y = ((y + h - 1) / h - 1) * h;


or simply:

y = (y - 1) / h * h; :-)

(you had a great idea!)


--
Vincenzo Mercuri

Billy Mays

unread,
Jul 12, 2010, 2:17:08 PM7/12/10
to
On 7/12/2010 1:54 PM, Vincenzo Mercuri wrote:
>
> or simply:
>
> y = (y - 1) / h * h; :-)
>
> (you had a great idea!)
>


I believe this would give the same result:

(y - 1) - (( y - 1) % h)

but without the multiply and divide.

--
Billy Mays
http://www.jpgdump.com <- My attempt at humor.

osmium

unread,
Jul 12, 2010, 3:15:45 PM7/12/10
to
Billy Mays wrote:

> On 7/12/2010 1:54 PM, Vincenzo Mercuri wrote:
>>
>> or simply:
>>
>> y = (y - 1) / h * h; :-)
>>
>> (you had a great idea!)
>>
>
>
> I believe this would give the same result:
>
> (y - 1) - (( y - 1) % h)
>
> but without the multiply and divide.

You think % is done without division?


Billy Mays

unread,
Jul 12, 2010, 3:43:33 PM7/12/10
to

It can be :)

/*******************************************************/
#include <stdio.h>
#include <stdint.h>

int main(int argc, char ** argv)
{
int y;
y = 31;
y = (((int64_t)(y-1) * 0x66666667LL) >> 34) ;
y = (y<<3) + (y<<1);
printf("%d\n", y);
return 0;
}
/*******************************************************/

not...@geocities.com

unread,
Jul 13, 2010, 12:55:35 AM7/13/10
to
What's C99?

Dean

Peter Nilsson

unread,
Jul 13, 2010, 1:01:29 AM7/13/10
to
On Jul 13, 2:55 pm, noth...@geocities.com wrote:

Please don't top-post.

> What's C99?

<http://www.lmgtfy.com/?q=c99&l=1>

> <snip>

--
Peter

Richard Heathfield

unread,
Jul 13, 2010, 6:23:52 AM7/13/10
to
not...@geocities.com wrote:
> What's C99?

It's what ISO fondly imagines C to be.

Nick Keighley

unread,
Jul 13, 2010, 6:44:24 AM7/13/10
to
don't top-post. Put your reply after or interspersed with the material
you are replying to. Trim anything you are not replying to taht does
not helpful context. I have corrected your post.

On 13 July, 05:55, noth...@geocities.com wrote:>
> On 07/12/2010 03:30:01:896 Vincenzo Mercuri <vincenzo.merc...@gmail.com> wrote:

<snip>

> > Yes, this is right for C90. Nevertheless compiling under C99
> > mode, you will always get -20
>

> What's C99?

The C programming language has been standardised originally by the
American standards organisation, ANSI. This standard was adopted,
essentially unchanged, by the International standards organistaion,
ISO. As the ANSI standard came out in 1989 it (and its ISO equivalent)
are often referred to as C89 (occaisionally as C90 (the date of ISO
adoption)). In 1999 ISO issued a new standard for C and this is often
referred to as C99. C99 tightened up some definitions including the
meaning of division for negative numbers.

Vincenzo Mercuri

unread,
Jul 13, 2010, 1:58:12 PM7/13/10
to
Billy Mays ha scritto:

Well, actually I don't know if the assembly implementation
of the '/' operator is so different from that of a set of
expressions with shift operators. But I think it is likely
the case. :-)

--
Vincenzo Mercuri

Nick Keighley

unread,
Jul 14, 2010, 3:32:55 AM7/14/10
to
On 13 July, 18:58, Vincenzo Mercuri <vincenzo.merc...@gmail.com>
wrote:

its quite common for compilers to substitute shifts for divides by
powers of 2


0 new messages