I am not quite sure what is math.ceiling doing here - c#

Can somebody please tell me what is math.ceiling function doing here because I think Math.Pow will do the job without it? You don't need the rest of the code to understand because the code would do the same without Math.Ceiling. I just need information whether Math.Ceiling makes sure that Math.Pow has really calculated its number in the right way or does it mean something else. Thanks in advance
a[i] = a[i-1] * 10 + 45 * (int)(Math.Ceiling(Math.Pow(10, i-1)));

The call is completely pointless. Since i is an index into the array, it must be a positive integer - otherwise, this will either crash (if i is 0 or less) due to not being a valid index into the array or not even compile in the first place (if i is not an integer at all). That being said, Math.pow is already guaranteed to return an integer in this case, so it will never make any difference in the output.

Math.ceiling() is the guarantee that your number will be an integer, like, if the pow returns a float number, Math.ceiling will round up the number.
Ex.: Pow returns 2.7, Math.ceiling returns 3.
Assuming that i is already an integer, there is no real need for the Math.ceiling() function, because the pow return will always be an integer.
Hope that is the answer you are looking for.

Related

How do I detect total loss of precision with Doubles?

When I run the following code, I get 0 printed on both lines:
Double a = 9.88131291682493E-324;
Double b = a*0.1D;
Console.WriteLine(b);
Console.WriteLine(BitConverter.DoubleToInt64Bits(b));
I would expect to get Double.NaN if an operation result gets out of range. Instead I get 0. It looks that to be able to detect when this happens I have to check:
Before the operation check if any of the operands is zero
After the operation, if neither of operands were zero, check if the result is zero. If not let it run. If it is zero, assign Double.NaN to it instead to indicate that it's not really a zero, it's just a result that can't be represented within this variable.
That's rather unwieldy. Is there a better way? What Double.NaN is designed for? I'm assuming some operations must have return it, surely designers did not put it there just in case? Is it possible that this is a bug in BCL? (I know unlikely, but, that's why I'd like to understand how that Double.NaN is supposed to work)
Update
By the way, this problem is not specific for double. decimal exposes it all the same:
Decimal a = 0.0000000000000000000000000001m;
Decimal b = a* 0.1m;
Console.WriteLine(b);
That also gives zero.
In my case I need double, because I need the range they provide (I'm working on probabilistic calculations) and I'm not that worried about precision.
What I need though is to be able to detect when my results stop mean anything, that is when calculations drop the value so low, that it can no longer be presented by double.
Is there a practical way of detecting this?
Double works exactly according to the floating point numbers specification, IEEE 754. So no, it's not an error in BCL - it's just the way IEEE 754 floating points work.
The reason, of course, is that it's not what floats are designed for at all. Instead, you might want to use decimal, which is a precise decimal number, unlike float/double.
There's a few special values in floating point numbers, with different meanings:
Infinity - e.g. 1f / 0f.
-Infinity - e.g. -1f / 0f.
NaN - e.g. 0f / 0f or Math.Sqrt(-1)
However, as the commenters below noted, while decimal does in fact check for overflows, coming too close to zero is not considered an overflow, just like with floating point numbers. So if you really need to check for this, you will have to make your own * and / methods. With decimal numbers, you shouldn't really care, though.
If you need this kind of precision for multiplication and division (that is, you want your divisions to be reversible by multiplication), you should probably use rational numbers instead - two integers (big integers if necessary). And use a checked context - that will produce an exception on overflow.
IEEE 754 in fact does handle underflow. There's two problems:
The return value is 0 (or -1 for negative undreflow). The exception flag for underflow is set, but there's no way to get that in .NET.
This only occurs for the loss of precision when you get too close to zero. But you lost most of your precision way long before that. Whatever "precise" number you had is long gone - the operations are not reversible, and they are not precise.
So if you really do care about reversibility etc., stick to rational numbers. Neither decimal nor double will work, C# or not. If you're not that precise, you shouldn't care about underflows anyway - just pick the lowest reasonable number, and declare anything under that as "invalid"; may sure you're far away from the actual maximum precision - double.Epsilon will not help, obviously.
All you need is epsilon.
This is a "small number" which is small enough so you're no longer interested in.
You could use:
double epsilon = 1E-50;
and whenever one of your factors gets smaller than epislon you take action (for example treat it like 0.0)

A simple C# Statement works unexpected

I've got this line of code:
int WStoneCost = PriceMethod.StoneCost / 100 * AP;
While PriceMethod.StoneCost is equal to 25 and AP is equal to 70.
I've checked it using breakpoints and I can't understand why do I get zero after I run this line. (WStoneCost is equal to zero)
Is it just a wrong symbol or am I doing something wrong? Thanks in advance.
And how to get a correct double at the end? Like 17.5
You are doing integer division, so 25/100 is 0, not 0.25, and hence 0 * 70 is 0. Since your result variable is also an int it's unclear what result you are expecting, but you could reorder the operations to get a non-zero answer:
int WStoneCost = (PriceMethod.StoneCost * AP)/ 100 ;
It's still integer division, but with your inputs will divide 25*70 (1,750) by 100, which will give you 17.
If you want a floating-point decimal result, just use 100m:
decimal WStoneCost = (PriceMethod.StoneCost * AP)/ 100m ;
Since the literal 100m is a decimal, then the compiler will use floating-point decimal division, which will give you a decimal result.
And how to get a correct double at the end? Like 17.5
Your question and both of the two answers given so far indicate that all three of you want to do something dangerously wrong. You are doing financial calculations so you should always be using decimal, never double. double is for physics calculations, not financial calculations.
I agree with JonathanWood. According to the values that you provided, your answer is going to produce a fractional number. Therefore, you need WStoneCost to be a double or a float. Also, you might want to use partentheses in your equations to ensure that the order of operations is carried out to your expectations.
Hope this helps!
-Gary The Bard

Am I going crazy or is Math.Pow broken?

I used the base converter from here and changed it to work with ulong values, but when converting large numbers, specifically numbers higher than 16677181699666568 it was returning incorrect values. I started looking into this and discovered that Math.Pow(3, 34) returns the value 16677181699666568, when actually 3^34 is 16677181699666569. This therefore throws a spanner in the works for me. I assume this is just an issue with double precision within the Pow method? Is my easiest fix just to create my own Pow that takes ulong values?
If so, what's the quickest way to do Pow? I assume there's something faster than a for loop with multiplication each time.
You can use BigInteger.Pow. Or use my power method for long.
The problem is that Math.Pow returns a double, and the closest double value to 16677181699666569 is 16677181699666568.
So without getting Math.Pow involved:
long accurate = 16677181699666569;
double closestDouble = accurate;
// See http://pobox.com/~skeet/csharp/DoubleConverter.cs
Console.WriteLine(DoubleConverter.ToExactString(closestDouble));
That prints 16677181699666568.
In other words whatever Math.Pow does internally, it can't return a result that's more accurate than the one you're getting.
As others have said, BigInteger.Pow is your friend if you're using .NET 4.
Read What Every Computer Scientist Should Know About Floating-Point
Floating point types are an approximation, the rounding you see is normal.
If you want exact results use BigInteger.
I assume this is just an issue with
double precision within the Pow
method?
Yes.
Is my easiest fix just to create my
own Pow that takes ulong values?
You can use BigInteger.Pow.
If you're using .NET Framework 4, Microsoft has included a new BigInteger class that lets you manipulate large numbers.
http://msdn.microsoft.com/en-us/library/system.numerics.biginteger.aspx
Alternatively, you can use a nice library that someone else created:
http://intx.codeplex.com/ (IntX library)

Why doesn't Math.Round/Floor/Ceiling return long or int?

Every time I use Math.Round/Floor/Ceiling I always cast to int (or perhaps long if necessary). Why exactly do they return double if it's always returning an integer.
The result might not fit into an int (or a long). The range of a double is much greater.
Approximate range of double: ±5.0 × 10−324 to ±1.7 × 10308
(Source)
I agree with Mark's answer that the result might not fit in a long, but you might wonder: what if C# had a much longer long type? Well, here's what happens in Python with it's arbitary-length integers:
>>> round(1.23e45)
1229999999999999973814869011019624571608236032
Most of the digits are "noise" from the floating-point rounding error. Perhaps part of the motivation for Round/Floor/Ceiling returning double in C# was to avoid the illusion of false precision.
An alternative explanation is that the .NET Math module uses code written in C, in which floor and ceil return floating-point types.
Range arguments aside, none of these answers addresses what, to me, is a fundamental problem with returning a floating point number when you really want an exact integer. It seems to me that the calculated floating point number could be less than or greater than the desired integer by a small round off error, so the cast operation could create an off by one error. I would think that, instead of casting, you need to apply an integer (not double) round-nearest function to the double result of floor(). Or else write your own code. The C library versions of floor() and ceil() are very slow anyway.
Is this true, or am I missing something? There is something about an exact representation of integers in an IEEE floating point standard, but I am not sure whether or not this makes the cast safe.
I would rather have range checking in the function (if it is needed to avoid overflow) and return a long. For my own private code, I can skip the range checking. I have been doing this:
long int_floor(double x)
{
double remainder;
long truncate;
truncate = (long) x; // rounds down if + x, up if negative x
remainder = x - truncate; // normally + for + x, - for - x
//....Adjust down (toward -infinity) for negative x, negative remainder
if (remainder < 0 && x < 0)
return truncate - 1;
else
return truncate;
}
Counterparts exist for ceil() and round() with different considerations for negative and positive numbers.
There is no reason given on the docs that I could find. My best guess is that if you are working with doubles, chances are you would want any operations on doubles to return a double. Rounding it to cast to an int was deemed by the language designer less common then rounding and keeping as a double.
You could write your own method that cast it to an int for you in about 2 lines of code, and much less work than posting a question on stack overflow...

C# - Math.Round

I am trying to understand how to round to the nearest tenths position with C#. For instance, I have a value that is of type double. This double is currently set to 10.75. However, I need to round and then truncate everything past the tenths position. In this case, I am seeking a value of 10.8. How do I round to the tenths position in C#?
Thank you!
Math.Round(yourNumber, 1)
The second parameter is number of decimal places to round to. In your case you want 1 decimal place as an end result.
You simply need to use the overload of Math.Round that takes the decimals parameter.
Math.Round(10.75, 1) // returns 10.8
Just for comparison:
Math.Round(10.75) // returns 11
Math.Round(10.75, 0) // returns 11
Math.Round(10.75, 2) // returns 10.75
Since you Used Math.Round() in your title, I'm going to assume you've already tried the basic Math.Round(10.75,1) approach and it returns something you don't expect. With that in mind, I suggest looking at some of the different overloads for the function, specifically one that accepts a MidPointRounding enum:
http://msdn.microsoft.com/en-us/library/f5898377.aspx
Do you really need to round it, or can you just format it for printing but allow the variable itself to hold its precision? Something like:
decimal value = 10.75;
value.ToString ("#.#");
If you just want to "cut" everything after the first decimal, this shoudl work :
return Math.Round(value * 10)/10

Categories

Resources