ceil() and int values

T

Test

I need to get a ceil value from two integers

When I use as follows:
int i5,i2;
i5=5;i2=2;
i=ceil(i5/i2);
I get 2 for obvious reasons.

However when I use as follows:
int i5,i2;
i5=5;i2=2;
i=ceil((double)i5/i2);
I get 3 but from past experience I doubt some compilers will return 2.

Safest way to get 3 appears to be lengthy
int i5,i2;
i5=5;i2=2;
i=ceil((double)((double)i5/(double)i2));

What is the "cleanest" but most compatible way? My program in this instance
always uses integers greater than zero and less than 128. Is there another
(speedier?) way other than using ceil()?
 
E

Eric Sosman

I need to get a ceil value from two integers

When I use as follows:
int i5,i2;
i5=5;i2=2;
i=ceil(i5/i2);
I get 2 for obvious reasons.

However when I use as follows:
int i5,i2;
i5=5;i2=2;
i=ceil((double)i5/i2);
I get 3 but from past experience I doubt some compilers will return 2.

Safest way to get 3 appears to be lengthy
int i5,i2;
i5=5;i2=2;
i=ceil((double)((double)i5/(double)i2));

What is the "cleanest" but most compatible way? My program in this instance
always uses integers greater than zero and less than 128. Is there another
(speedier?) way other than using ceil()?

i = (i5 + i2 - 1) / i2;
 
M

Malcolm McLean

On Sun, 13 Oct 2013 11:31:57 +0300, Test <[email protected]>
int x = i5/i2;
if(x * i2 < i5)
x++;

it may or may not be faster, often floating point is pipelined separately
to integer calculations, so it's very difficult to say whether removing a
floating point operation will speed up code or not.
 
J

James Kuyper

Baring a broken compiler, 3 is the only possible result. Casting i5
to a double will then force i2 to a matching promotion, so that the
(double) division can occur. So the result *must* be 2.5, and
ceil(2.5) must be 3.0. Nor should there be any question of how that
converts back to an int.

While I would agree with you that any compiler which produces any value
other than 3 is broken, such a compiler could still be fully conforming:

"The accuracy of the floating-point operations (+, -, *, /) and of the
library functions in <math.h> and <complex.h> that return floating-point
results is implementation defined, as is the accuracy of the conversion
between floating-point internal representations and string
representations performed by the library functions in <stdio.h>,
<stdlib.h>, and <wchar.h>. The implementation may state that the
accuracy is unknown." (5.2.2.4.2p6).

Division is one of those operations, and ceil() is one of those
functions, so there are two different opportunities for arbitrarily bad
accuracy to be fully conforming, so long as the implementation documents
the fact that it is that bad.

If the implementation chooses to pre-#define __STDC_IEC_559__, the
requirements are much stricter, and a conforming implementation must
produce 3.
 
S

Seebs

However when I use as follows:
int i5,i2;
i5=5;i2=2;
i=ceil((double)i5/i2);
I get 3 but from past experience I doubt some compilers will return 2.

.... I doubt very much that any compiler will yield 2, because I don't
think C's ever worked in a way where this could produce anything but 3.
What is the "cleanest" but most compatible way? My program in this instance
always uses integers greater than zero and less than 128. Is there another
(speedier?) way other than using ceil()?

If they're always smallish positive integers:
i = (i5 + 1) / i2;

-s
 
M

Malcolm McLean

Seebs wrote:







Close, but no cigar. Eric got it right ;-)
His fails on i5 + i2 -1 > INT_MAX, but it's faster solution than mine,
so the one to be preferred.
 
J

James Harris

Malcolm McLean said:
His fails on i5 + i2 -1 > INT_MAX, but it's faster solution than mine,
so the one to be preferred.

I don't understand. Eric's was i = (i5 + i2 - 1) / i2. How can it be faster?
Unless the divisor is a constant both will be dominated by the cost of the
division.

James
 
J

James Kuyper

I don't understand. Eric's was i = (i5 + i2 - 1) / i2. How can it be faster?
Unless the divisor is a constant both will be dominated by the cost of the
division.

Malcolm's solution was not the one given above; it was:
 
J

James Kuyper

... I doubt very much that any compiler will yield 2, because I don't
think C's ever worked in a way where this could produce anything but 3.


If they're always smallish positive integers:
i = (i5 + 1) / i2;

I suppose that's correct, for a suitable definition of "smallish". The
smallest pair of positive values for which it gives the wrong result is
i5==1, i2==3, for which the correct result is 1, and your formula gives
0. That's a pretty restrictive definition of "smallish".
 
J

James Kuyper

... I doubt very much that any compiler will yield 2, because I don't
think C's ever worked in a way where this could produce anything but 3.


If they're always smallish positive integers:
i = (i5 + 1) / i2;

Restricting consideration to the positive integers, that gives the wrong
result whenever i2==1 || i5%i2 < i2-1. Example: i5 == 1, i2 == 3; the
correct result should be 1, your expression gives 0.
 
E

Eric Sosman

[...]

I don't understand. Eric's was i = (i5 + i2 - 1) / i2. How can it be faster?
Unless the divisor is a constant both will be dominated by the cost of the
division.

If speed is what most concerns you, it's hard to beat

i = 0;
 
M

Malcolm McLean

I don't understand. Eric's was i = (i5 + i2 - 1) / i2. How can it be faster?

Unless the divisor is a constant both will be dominated by the cost of the
division.
Mine has does a multiply then has an if statement. Branches tend to be quite
expensive, whilst addition is always an extremely cheap operation.
However Eric's won't give correct results in i5 + i2 overflows, whilst
mine will. However that's unlikely, so for most purposes Eric's solution
is the better one.
 
B

Ben Bacarisse

Malcolm McLean said:
Mine has does a multiply then has an if statement. Branches tend to be quite
expensive, whilst addition is always an extremely cheap operation.

Your if:

if (x*i2 < i5) x++;

can be written:

x += x*i2 < i5;

which may well compile without a branch. Indeed, the original might do
as well. In fact it does in gcc -- only with -O0 do you get a branch.

<snip>
 
J

James Harris

Malcolm McLean said:
Mine has does a multiply then has an if statement. Branches tend to be
quite
expensive, whilst addition is always an extremely cheap operation.
However Eric's won't give correct results in i5 + i2 overflows, whilst
mine will. However that's unlikely, so for most purposes Eric's solution
is the better one.

Ah, sorry. I read Peter's solution as yours. Yes, branches can be slow if
they are unpredictable but will be very fast on many CPUs if the data allow
them to be predicted well.

James
 
G

glen herrmannsfeldt

James Kuyper said:
On 10/15/2013 03:34 AM, Seebs wrote:
(snip)

That should be true, but for larger i5 you might get to the point
where floating point rounds the wrong way.

(snip)
Restricting consideration to the positive integers, that gives
the wrong result whenever i2==1 || i5%i2 < i2-1.
Example: i5 == 1, i2 == 3; the correct result should be 1,
your expression gives 0.

But note that to the OP, i2=2. The OP didn't ask for a
generalization, but only for this one specific case.

-- glen
 
J

James Kuyper

That should be true, but for larger i5 you might get to the point
where floating point rounds the wrong way.

True - that would require that INT_MAX*DBL_EPSILON > 1; which is
unlikely, but permitted. It could be an issue on 64bit machines.
But note that to the OP, i2=2. The OP didn't ask for a
generalization, but only for this one specific case.

If he didn't want generalization, he could have replaced i5 with 5, and
i2 with 2, or he could have gone even farther and simply written

i = 3;

I think he was looking for a generalization.
 
S

Seebs

His fails on i5 + i2 -1 > INT_MAX, but it's faster solution than mine,
so the one to be preferred.

I explicitly stated the necessary qualifier, because the OP had stated that
things were in a range of 0-128 or so, as I recall. But for that case it's
fine, so far as I know.

-s
 
S

Seebs

Restricting consideration to the positive integers, that gives the wrong
result whenever i2==1 || i5%i2 < i2-1. Example: i5 == 1, i2 == 3; the
correct result should be 1, your expression gives 0.

D'oh. I think I somehow formed the theory that we only cared about i2 == 2.

-s
 
B

blmblm

Tying this in, sort of, with the other thread in which usage of "doubt"
is (was?) being debated once again ....

Here's an instance of "doubt" being used in a way that -- IMO anyway --
is potentially ambiguous.

To a US-English speaker (or to this one anyway), it -- well, I'd
say that it means "my guess is that there are no compilers that
will return 2" except that I'd be more likely to write "I doubt
any compilers would return 2".

In context it appears to mean that maybe some compilers *do* return 2.

"Just sayin'", maybe.

i = (i5 + i2 - 1) / i2;


Now there's a trick .... I learned it in a long-ago PPOE and think
it's kind of a clever hack. But I don't know that I've observed
anyone other than the long-ago colleague (and myself) using it.
But apparently some others in this thread know about it, and also
know that it *can* run up against problems with overflow. "Hm!" ?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top