Integer from a decimal.

C

ChrisM

Hi Guys,

I'm looking for a function that will return the lowest integer that is
greater than or equal to a decimal number.

eg.

3.1(decimal) returns 4(integer)
3.9(decimal) returns 4(integer)
4.0(decimal) returns 4(integer)

I guess I can do somthing with Math.Ceiling, but that seems to need a Double
as an input and returns a Double. Is there a neat way, or am I going to have
to cast my Decimal to a Double, then somehow convert the result to an
Integer by hand?

Thanks,

Chris.
 
T

Tom Porterfield

ChrisM said:
Hi Guys,

I'm looking for a function that will return the lowest integer that is
greater than or equal to a decimal number.

eg.

3.1(decimal) returns 4(integer)
3.9(decimal) returns 4(integer)
4.0(decimal) returns 4(integer)

I guess I can do somthing with Math.Ceiling, but that seems to need a
Double as an input and returns a Double. Is there a neat way, or am I
going to have to cast my Decimal to a Double, then somehow convert the
result to an Integer by hand?

You can convert decimal to double without too much problem. Or you can
write your own Ceiling to handle this.

static int ceil(decimal d)
{
if (d > 0)
return (int)d == d ? (int)d : ((int)d) + 1;
else
return (int)d;
}
 
J

Jon Skeet [C# MVP]

ChrisM said:
I'm looking for a function that will return the lowest integer that is
greater than or equal to a decimal number.

eg.

3.1(decimal) returns 4(integer)
3.9(decimal) returns 4(integer)
4.0(decimal) returns 4(integer)

I guess I can do somthing with Math.Ceiling, but that seems to need a Double
as an input and returns a Double. Is there a neat way, or am I going to have
to cast my Decimal to a Double, then somehow convert the result to an
Integer by hand?

There's an overload of Math.Ceiling which takes and returns a decimal,
which you'd then cast to int:

using System;
using System.Diagnostics;

class Test
{
static void Main()
{
Debug.Assert(CeilingOfDecimalAsInt(3.1m)==4);
Debug.Assert(CeilingOfDecimalAsInt(3.9m)==4);
Debug.Assert(CeilingOfDecimalAsInt(4m)==4);
}

static int CeilingOfDecimalAsInt(decimal m)
{
return (int) Math.Ceiling(m);
}
}

(The method name isn't a real suggested one :)
 
T

Tom Porterfield

Tom said:
You can convert decimal to double without too much problem. Or you can
write your own Ceiling to handle this.

static int ceil(decimal d)
{
if (d > 0)
return (int)d == d ? (int)d : ((int)d) + 1;
else
return (int)d;
}

Or in the 2.0 manner:

static int ceil(decimal d)
{
return (int)-(decimal.Floor(-d));
}
 
C

ChrisM

Jon Skeet said:
There's an overload of Math.Ceiling which takes and returns a decimal,
which you'd then cast to int:

using System;
using System.Diagnostics;

class Test
{
static void Main()
{
Debug.Assert(CeilingOfDecimalAsInt(3.1m)==4);
Debug.Assert(CeilingOfDecimalAsInt(3.9m)==4);
Debug.Assert(CeilingOfDecimalAsInt(4m)==4);
}

static int CeilingOfDecimalAsInt(decimal m)
{
return (int) Math.Ceiling(m);
}
}

(The method name isn't a real suggested one :)

Thanks Tom and Jon for your answers, I can see how to do it now. I should
have been able to do it anyway. Think it must have been that 'Monday
Feeling'...
Can't seem to find a way of getting Math.Ceiling() to take a decimal. Is
that a .Net2.0 addition? But anyway, casting to a double, or doing as Tom
suggests and writing my own little function seems fairly straight forward...

Thanks again,

Chris.
 
J

Jon Skeet [C# MVP]

ChrisM said:
Thanks Tom and Jon for your answers, I can see how to do it now. I should
have been able to do it anyway. Think it must have been that 'Monday
Feeling'...
Can't seem to find a way of getting Math.Ceiling() to take a decimal. Is
that a .Net2.0 addition? But anyway, casting to a double, or doing as Tom
suggests and writing my own little function seems fairly straight forward...

Yes, it's a 2.0 addition. Casting to a double has issues. For instance,
consider this .NET 2.0 program:

using System;

class Test
{
static void Main()
{
decimal m = 5.0000000000000000001m;
Console.WriteLine (Math.Ceiling(m));
Console.WriteLine (Math.Ceiling((double)m));
}
}

It produces
5
6

because the nearest double to 5.0000000000000000001 is exactly 5.

Tom's "int casting" answer is a good one.

Jon
 
C

ChrisM

Jon Skeet said:
Yes, it's a 2.0 addition. Casting to a double has issues. For instance,
consider this .NET 2.0 program:

using System;

class Test
{
static void Main()
{
decimal m = 5.0000000000000000001m;
Console.WriteLine (Math.Ceiling(m));
Console.WriteLine (Math.Ceiling((double)m));
}
}

It produces
5
6

because the nearest double to 5.0000000000000000001 is exactly 5.

Tom's "int casting" answer is a good one.

Jon
Probably I'm just be
 
C

ChrisM

Jon Skeet said:
Yes, it's a 2.0 addition. Casting to a double has issues. For instance,
consider this .NET 2.0 program:

using System;

class Test
{
static void Main()
{
decimal m = 5.0000000000000000001m;
Console.WriteLine (Math.Ceiling(m));
Console.WriteLine (Math.Ceiling((double)m));
}
}

It produces
5
6

because the nearest double to 5.0000000000000000001 is exactly 5.

Tom's "int casting" answer is a good one.

Jon

It doesn't matter here, as the numbers are rarely going to be finer than .5,
maybe .25 or .333 but I'm curious:
probably just being stupid again, but I don't understand why that happens.
if (double)5.000000000000001m is 5
then why does Math.Ceiling((double)5.000000000000001m) equal 6
when Math.Ceiling((double)5m) is 5 ??

Cheers,

Chris.
 
J

Jon Skeet [C# MVP]

ChrisM said:
It doesn't matter here, as the numbers are rarely going to be finer than .5,
maybe .25 or .333 but I'm curious:
probably just being stupid again, but I don't understand why that happens.
if (double)5.000000000000001m is 5
then why does Math.Ceiling((double)5.000000000000001m) equal 6
when Math.Ceiling((double)5m) is 5 ??

Because I'm careless, unfortunately - I copied the numbers down the
wrong way! The point I was trying to make stands though :)
 
T

Tom Porterfield

ChrisM said:
It doesn't matter here, as the numbers are rarely going to be finer than
.5, maybe .25 or .333 but I'm curious:
probably just being stupid again, but I don't understand why that happens.
if (double)5.000000000000001m is 5
then why does Math.Ceiling((double)5.000000000000001m) equal 6
when Math.Ceiling((double)5m) is 5 ??

It still matters, Jon was using that as an example to show how inprecise
floating point arithmetic in .NET might lead to results that you hadn't
anticipated. There are several good articles on this subject including
http://www.extremeoptimization.com/resources/Articles/FPDotNetConceptsAndFormats.aspx.
The point being that anytime you store a number in a floating point time
(double or single), the value stored may not exactly be what you thought you
were storing. Consider the following short example:

double d = 1.0;
for (long i = 1; i < 100000000; i++, d++)
{
i = i * i / i;
d = d * d / d;
if (i != d)
{
Console.WriteLine ("{0} == {1} is {2}", i, d, (i == d));
break;
}
}

Look at this and predict what, if anything, will be written to the console
before the program ends. The output on my machine using the 1.1 framework
is:

94906267 == 94906267 is False

Jon got his results transposed, the output would be
6
5

Again the point being the results are not what you might anticipate if you
simply looked at the code and that decimal m = 5.000000000000001m;
Math.Ceiling(m) != Math.Ceiling((double)m) because m.Equals((double)m) ==
false.
 
C

ChrisM

Tom Porterfield said:
It still matters, Jon was using that as an example to show how inprecise
floating point arithmetic in .NET might lead to results that you hadn't
anticipated. There are several good articles on this subject including
http://www.extremeoptimization.com/resources/Articles/FPDotNetConceptsAndFormats.aspx.
The point being that anytime you store a number in a floating point time
(double or single), the value stored may not exactly be what you thought
you were storing. Consider the following short example:

Thanks for that,
 
C

ChrisM

Tom Porterfield said:
It still matters, Jon was using that as an example to show how inprecise
floating point arithmetic in .NET might lead to results that you hadn't
anticipated. There are several good articles on this subject including
http://www.extremeoptimization.com/resources/Articles/FPDotNetConceptsAndFormats.aspx.
The point being that anytime you store a number in a floating point time
(double or single), the value stored may not exactly be what you thought
you were storing. Consider the following short example:

Thanks for the explanation there, Tom. I do understand the dangers of
floating point arithmetic from a precision point of view. What I meant by
not mattering though, was that in this particular case, the numbers should
be such that any inaccuracies will be insignificant. Even if they do come
out wrong under certain rare conditions, all I'm doing is calculating the
number of labels to print (I need 1 label for each whole or fractional part
(so 3.5 would need 4 labels). If occasionally 1 extra label comes out,
no-one will care, or even notice.

I might use that nice little function that you posted earlier though, then
there is no danger of getting it wrong, just to 'get it right'

Cheers,

Chris.
 

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

Top