# Re: Rounding

Discussion in 'C Programming' started by Vincenzo Mercuri, Jul 12, 2010.

1. ### Vincenzo MercuriGuest

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;

--
Vincenzo Mercuri

Vincenzo Mercuri, Jul 12, 2010

2. ### Billy MaysGuest

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.

Billy Mays, Jul 12, 2010

3. ### osmiumGuest

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?

osmium, Jul 12, 2010
4. ### Billy MaysGuest

On 7/12/2010 3:15 PM, osmium wrote:
> 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?
>
>

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;
}
/*******************************************************/

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

Billy Mays, Jul 12, 2010
5. ### Vincenzo MercuriGuest

Billy Mays ha scritto:
> On 7/12/2010 3:15 PM, osmium wrote:
>> 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?
>>
>>

>
> 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;
> }
> /*******************************************************/
>

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

Vincenzo Mercuri, Jul 13, 2010
6. ### Nick KeighleyGuest

On 13 July, 18:58, Vincenzo Mercuri <>
wrote:
> Billy Mays ha scritto:
>
>
>
>
>
> > On 7/12/2010 3:15 PM, osmium wrote:
> >> 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?

>
> > 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;
> > }
> > /*******************************************************/

>
> 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.

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

Nick Keighley, Jul 14, 2010