While "we all know" that x == y can be problematic, where x and y are floating point values, this question is a bit more specific:
int x = random.Next(SOME_UPPER_LIMIT);
float r = x;
// Is the following ALWAYS true?
r == x
Now, since the range of float of is much larger than that of integers (but the precision is insufficient to uniquely present integers at the edges), it would be nice if responses to this question also addressed which values of x the above can be guaranteed for, if it can be guaranteed at all.
Currently my code is making this assumption (for relatively small values of x) - I would like to make sure that I won't get bitten :)
This will fail with "not equal: 16777217" (cast float -> int):
for (int i = 0; i < int.MaxValue; i++) {
float f = i;
if ((int)f != i) throw new Exception("not equal " + i);
}
This similar code will not fail (only int -> float); however, due to loss in the conversion, there are several floats that can "equal" the same integer, and may represent a silent bug:
for (int i = 0; i < int.MaxValue; i++) {
float f = i;
if (f != i) throw new Exception("not equal " + i);
}
Yes, the comparison will always be true, whatever value the int is.
The int will be converted to a float to do the conversion, and the first conversion to float will always give the same result as the second conversion.
Consider:
int x = [any integer value];
float y = x;
float z = x;
The values of y and z will always be the same. If the conversion loses precision, both conversions will lose the precision in exactly the same way.
If you convert the float back to int to to the comparison, that's another matter.
Also, note that even if a specific int value converted to float always results in the same float value, that doesn't mean that the float value has to be unique for that int value. There are int values where (float)x == (float)(x+1) would be true.
When comparing an int and a float, the int is implicitly cast to a float. This ensures the same loss of precision happens, and so the comparison will happen to always be true. As long as you don't disturb the implicit cast or do arithmetic, the equality should hold. For example, if you write this:
bool AlwaysTrue(int i) {
return i == (float)i;
}
there is an implicit cast, so it's equivalent to this function that should always return true:
bool AlwaysTrue(int i) {
return (float)i == (float)i;
}
but if you write this:
bool SometimesTrue(int i) {
return i == (int)(float)i;
}
then there is no more implicit cast and the loss of precision only happens on the right side. The result may be false. Similarly, if you write this:
bool SometimesTrue(int i) {
return 1 + i == 1 + (float)i;
}
then the loss of precision might not be equivalent on both sides. The result may be false.
The following experiment reveals that the answer is you do not have that edge case where equality is not true
static void Main(string[] args)
{
Parallel.For(int.MinValue, int.MaxValue, (x) =>
{
float r = x;
// Is the following ALWAYS true?
bool equal = r == x;
if (!equal) Console.WriteLine("Unequal: " + x);
});
Console.WriteLine("Done");
Console.ReadKey();
return;
}
It seems reasonable that the conversions
float f = i;
and
if ((int)f != i)
should follow the same rules. This proves that int -> float and float -> int conversions are a bijection.
NOTE: the experiment code actually doesn't test the edge case int.MaxValue because Parallel.For's to parameter is exclusive, but I tested that value separately and it also passes the test.
I ran this code without an exception being thrown:
for (int x = Int16.MinValue; x < Int16.MaxValue; x++)
{
float r = x;
if (r != x)
{
throw new Exception("Failed at: " + x);
}
}
Still waiting on (didn't complete this test because it took too long, never threw an exception though while running):
for (long x = Int64.MinValue; x < Int64.MaxValue; x++)
{
float r = x;
if (r != x)
{
throw new Exception("Failed at: " + x);
}
}
Went back and ran your example with a caveat, this was the output:
[Exception: not equal 16777217 ?= 1.677722E+07 ?= 16777216]
for (int i = 0; i < int.MaxValue; i++)
{
float f = i;
if ((int)f != i) throw new Exception("not equal " + i + " ?= " + f + " ?= " + (int)f);
}
My understanding of floating point arithmetic calculations is that they are handled by the CPU, which solely determines your precision. Therefore there is no definite value above which floats lose precision.
I had thought that the x86 architecture, for instance, guaranteed a minimum, but I've been proven wrong.
Related
I need to do divide the number which equals to sum of some big values. But after a while, it overflows and it equals to a negative number. I tried to use BigInteger,decimal and double but it doesn't work again.
Error message:System.ArgumentException 'Value of '256' is not valid for 'red'. 'red' should be greater than or equal to 0 and less than or equal to 255.'
Edit: When i checked value of GaussFiltresi[syc] i have seen that :'GaussFiltresi[syc]' threw an exception of type 'System.IndexOutOfRangeException'
#region Gaussian Filter
public void gaussianfilter (int SablonBoyutu,Bitmap GirisResmi,Bitmap CikisResmi)
{
int ResimGenisligi = GirisResmi.Width;
int ResimYuksekligi = GirisResmi.Height;
int syc = 0;
BigInteger toplamR;
BigInteger filtrekatsayitoplami;
BigInteger ortalamaR;
int kernelsinir = ((SablonBoyutu - 1) / 2);
for ( i = -kernelsinir; i <= kernelsinir; i++)
{
for ( j = -kernelsinir; j <= kernelsinir; j++)
{
//some calculations
}
}
for (int x = (kernelsinir); x < ResimGenisligi - kernelsinir; x++)
{
for (int z = (kernelsinir); z < ResimGenisligi - kernelsinir; z++)
{
syc = 0;
toplamR = 0;
for (int y = -(kernelsinir); y <= kernelsinir; y++)
{
for (int d = -(kernelsinir); d <= kernelsinir; d++)
{
OkunanRenk = GirisResmi.GetPixel(x + y, d + z);
toplamR += GaussFiltresi[syc] * (BigInteger)(OkunanRenk.R);
//toplam R=1662424090 and GaussFiltresi[syc] = 5389698 before overflowing
syc++;
}
}
ortalamaR = toplamR / filtrekatsayitoplami; //toplamR is negative
CikisResmi.SetPixel(x, z, Color.FromArgb((int)ortalamaR, (int)ortalamaR,(int)ortalamaR));
}
}
}
#endregion
With a reference to System.Numerics.dll, you can use BigInteger instead of Int64 (a.k.a. long).
Another option is to use double that does not overflow (to PositiveInfinity) before 10**308, or 1e+308. Or decimal that goes to more than 1e+28m.
Update after comments: Your expression:
GaussFiltresi[syc] * OkunanRenk.R
is an int times an int. In fact becomes 14650719 * 160, which gives -1950852256. To have the two operands promoted to BigInteger, such that the multiplication * will be multiplication of big-ints (that never overflow), cast either operand to BigInteger (the other will be promoted to BigInteger for free), just as I said in my comment:
GaussFiltresi[syc] * (BigInteger)(OkunanRenk.R)
so the entire statement becomes:
toplamR += GaussFiltresi[syc] * (BigInteger)(OkunanRenk.R);
A multiplication of an int by an int will be done as an int multiplication (and the result may "wrap around"). It is not changed by the fact that the result is going to be +=-ed to a BigInteger later. That was the reason why it did not work after your initial code changes.
I am having trouble calculating Knuth's arrow notation, which is ↑ and can be found here, within a function. What I've made so far is:
int arrowCount = (int)arrowNum.Value; // Part of
BigInteger a = (int)aNum.Value; // the input I
BigInteger b = (int)bNum.Value; // already have
BigInteger result = a;
BigInteger temp = a;
for(int i = 0; i < arrowCount; i++)
{
result = Power(temp, b);
temp = r;
b = a;
}
with power being
BigInteger Power(BigInteger Base, BigInteger Pow)
{
BigInteger x = Base;
for(int i = 0; i < (Pow-1); i++)
{
x *= Base;
}
return x;
}
but it's incorrect with it's values and I can't figure out a way to fix it. It can handle 1 arrow problems like 3↑3 (which is 3^3 = 9), but it can't handle any more arrows than that.
I need a way to figure out more arrows, such as 3↑↑3,
which should be 7625597484987 (3^27) and I get 19683 (27^3). If you could help me to figure how I could get the proper output and explain what it is I'm doing wrong, I would greatly appreciate it.
I wrote it in java, and use double for input parameter:
private static double knuthArrowMath(double a, double b, int arrowNum)
{
if( arrowNum == 1)
return Math.pow(a, b);
double result = a;
for (int i = 0; i < b - 1; i++)
{
result = knuthArrowMath(a, result, arrowNum - 1);
}
return result;
}
If you expect 7625597484987 (3^27) but get 19683 (27^3), isn't it then a simple matter of swapping the arguments when calling your power function?
Looking at your Power function your code snippet seems to call Power with temp as base and b as power:
int arrowCount = (int)arrowNum.Value; // Part of
BigInteger a = (int)aNum.Value; // the input I
BigInteger b = (int)bNum.Value; // already have
BigInteger result = a;
BigInteger temp = a;
for(int i = 0; i < arrowCount; i++)
{
result = Power(temp, b);
temp = result;
b = a;
}
Shouldn't temp an b be swapped so you get result = Power(b, temp) to get the desired result?
So pass 1 results calls Power(3, 3) resulting in temp = 27 and pass 2 calls Power(3, 27). The reason it only works for single arrow now is because swapping arguments for the first Power(base, power) call doesn't matter.
As you point out in your answer this doesn't cover all situations. Given the examples you provided I created this little console application:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Arrow(3, 3));
Console.WriteLine(Arrow(4, 4, 1));
Console.WriteLine(Arrow(3, 4, 1));
Console.ReadKey();
}
private static BigInteger Arrow(BigInteger baseNumber, BigInteger arrows)
{
return Arrow(baseNumber, baseNumber, arrows-1);
}
private static int Arrow(BigInteger baseNumber, BigInteger currentPower, BigInteger arrows)
{
Console.WriteLine("{0}^{1}", baseNumber, currentPower);
var result = Power(baseNumber, currentPower);
if (arrows == 1)
{
return result;
}
else
{
return Arrow(baseNumber, result, arrows - 1);
}
}
private static BigInteger Power(BigInteger number, BigInteger power)
{
int x = number;
for (int i = 0; i < (power - 1); i++)
{
x *= number;
}
return x;
}
}
I came up with a way to use the BigInteger.Pow() function.
It might look a little odd, but that is because the C# BigInterger.Pow(x, y) only accepts an int for y, and teterations have HUGE exponents. I had to "flip the script" and convert x^y = y^x for this specific case.
I didn't add in any error checking, and it expects all numbers to be positive ints.
I know this works for x^^2 and x^^3. I also know it works for 2^^4 and 2^^5. I don't have the computing power/memory/math knowledge to know if it works for any other numbers. 2^^4 and 2^^5 were the only ones I could check and test. It may work for other numbers but I was not able to confirm that.
int baseNum = 4;
int exp = 3;
// this example is 4^^3
BigInteger bigAnswer = tetration(baseNum, exp);
// Here is what the method that "does the work" looks like.
// This looks a little odd but that is because I am using BigInteger.Pow(x,y)
// Unfortunately, y can only be an int. Tetrations have huge exponents, so I had to figure out a
// way to have x^y work as y^x for this specific application
// no error checking in here, and it expects positive ints only
// I *know* this works for x^^2, x^^3, but I don't know if it works for
// any other number than 2 at ^^4 or higher
public static BigInteger tetration(int baseNum, int exp)
{
if (exp > 2)
{
exp = (int)Math.Pow(baseNum, (exp - 3));
}
else
{
exp = exp - 2;
}
Func<BigInteger, int, BigInteger> bigPowHelper = (x, y) => BigInteger.Pow(x, y);
BigInteger bigAnswer = baseNum;
for (int i = 0; i < Math.Pow(baseNum, exp); i++)
{
bigAnswer = bigPowHelper(bigAnswer, baseNum);
}
return bigAnswer;
}
Assume that I want to get sum of all squares from M to N. I googled a bit and found this formula:
(1^2 + 2^2 + 3^2 + ... + N^2) = (N * (N + 1) * (2N + 1)) / 6
so I write this code:
static void Main(string[] args)
{
const int from = 10;
const int to = 50000;
Console.WriteLine(SumSquares(from, to));
Console.WriteLine(SumSquares2(from, to));
}
static long SumSquares(int m, int n)
{
checked
{
long x = m - 1;
long y = n;
return (((y*(y + 1)*(2*y + 1)) - (x*(x + 1)*(2*x + 1)))/6);
}
}
static long SumSquares2(int m, int n)
{
long sum = 0;
for (int i = m; i <= n; ++i)
{
sum += i * i;
}
return sum;
}
it works fine until 40k, but when N becomes 50k it fails. Output for 50k:
41667916674715
25948336371355
Press any key to continue . . .
I think it's an overflow or something, so I added checked keyword and tried to change long to double, but I got the same result. How can it be explained? How to get correct result without loops?
Your second method is overflowing because you are using an int in the loop. Change it to a long as follows (and also add checked):
static long SumSquares2(int m, int n)
{
checked
{
long sum = 0;
for (long i = m; i <= n; ++i)
{
sum += i*i;
}
return sum;
}
}
What was going wrong is that i*i was being calculated internally as an int data type even though the result was being cast to a long data type (i.e. the variable sum), and so it overflowed.
While you are using long for the result, you are still using int for the operators. I would define M and N as long or even BigInteger, and the same for the result. If you do not, you are probably doing int arithmetic still, even though your result is of type long.
I tried your code, and got the results you got. But then I changed every int to long and got the two numbers to match, up to an N of 1600000.
Using BigInteger, I am up to 160000000 and still working ok (result for m=10 and n=160000000 is 13653333461333333359999715, both ways).
To use BigInteger, you will need to add a reference to the System.Numerics dll to your project, and you will need to have a statement at the top of your code including that library.
using System.Numerics;
namespace ConsoleFiddle
{
class Program
{
static void Main(string[] args)
{
BigInteger from = 10;
BigInteger to = 160000000;
Console.WriteLine(SumSquares(from, to));
Console.WriteLine(SumSquares2(from, to));
Console.ReadKey();
}
static BigInteger SumSquares(BigInteger m, BigInteger n)
{
checked
{
BigInteger x = m - 1;
BigInteger y = n;
return (((y * (y + 1) * (2 * y + 1)) - (x * (x + 1) * (2 * x + 1))) / 6);
}
}
static BigInteger SumSquares2(BigInteger m, BigInteger n)
{
checked
{
BigInteger sum = 0;
for (BigInteger i = m; i <= n; ++i)
{
sum += i * i;
}
return sum;
}
}
For an M of 4000000000000000000 (4 x 10^18), and an N of 4000000000100000000. This code still works and gives an immediate result with the first method (1600000016040000000400333333338333333350000000). With the second method it takes it a little while (100 million loop iterations) but gives the same result.
Most probably you are experiencing integer overflow, as the range of long is limited. Probably you have disabled exceptions for integer overflow, so no exception is thrown. The exceptions for integer overflow can be disabled and enabled in the project properties in Visual Studio, if I'm not mistaken.
I'm trying to write an implementation of the parking lot test for random number generators. Here are the sources that I'm getting my information about the test from: Intel math library documentation and Page 4 of this paper along with the phi function for probability density listed here.
I wrote an implementation of the test in C#. It uses a 100x100 grid whose values are initially set to null. I then use the random number generator to generate random integers for x and y. If that index of the grid and it's neighbors are empty, that index gets set to 1. Otherwise, nothing happens because there was a "crash".
I ran it using C# System.Random generator. I don't believe the results are correct because I always get very near 3079 points parked, which is about 500 short of the average I'm supposed to get. It's also yields a p-value of 2.21829146215425E-90.
My code is below. Does anyone have any experience with this or can anyone see something that I might be doing incorrectly in my implementation? Any help would be greatly appreciated.
private void RunParkingLotTest()
{
points = new int?[100,100];
int parked = 0;
for (int i = 0; i < 12000; i++)
{
int x = random.Next(100);
int y = random.Next(100);
if (IsSafeToPark(x, y))
{
points[x, y] = 1;
parked++;
}
}
Console.WriteLine("Parked: " + parked + "\nP value: " + PhiFunction((parked-3523)/21.9));
}
private bool IsSafeToPark(int x, int y)
{
return PointIsEmpty(x, y)
&& LeftOfPointIsEmpty(x, y)
&& RightOfPointIsEmpty(x, y)
&& BelowPointIsEmpty(x, y)
&& AbovePointIsEmpty(x, y);
}
private bool AbovePointIsEmpty(int x, int y)
{
if (y == 99)
{
return true;
}
else
return points[x, y + 1] == null;
}
private bool BelowPointIsEmpty(int x, int y)
{
if (y == 0)
{
return true;
}
else
return points[x, y - 1] == null;
}
private bool RightOfPointIsEmpty(int x, int y)
{
if (x == 99)
{
return true;
}
else
return points[x + 1, y] == null;
}
private bool LeftOfPointIsEmpty(int x, int y)
{
if (x == 0)
{
return true;
}
else
return points[x - 1, y] == null;
}
private bool PointIsEmpty(int x, int y)
{
return points[x, y] == null;
}
private double PhiFunction(double x)
{
//ϕ(x) = (2π)−½e−x2/2
return ((1 / Math.Sqrt(2 * Math.PI)) * Math.Exp(-(Math.Pow(x, 2)) / 2));
}
edit - The problems with my original implementation were
I was plotting squares instead of disks
I only plotted points at integer values. I should have used decimal values instead.
As a result of the above two, I needed to change my distance check
Thanks to Chris Sinclair and mine z for help in figuring this out. The final code is posted below.
I'm going to take a stab at this, and admittedly, I have not attempted any such test, so forgive me if I'm way off. In general though, the .NET Random implementation is pretty good and I've never had issues with it, so I wouldn't suspect that initially especially since you're properly reusing the same instance instead of creating new ones.
Reading from the parking.pdf, and from the Intel documentation, it seems that they're using discs, and compute the distance from their centre points. Your implementation is using squares (array of 1 distance between spots) and thus ignoring diagonals.
From the pdf:
If disks were being used, the distance between the particles r =
p(x(i) − z)2 + (y(i) − z)2 would need to be less than or equal to one.
Does it matter whether one uses disks or squares? An indication of the
importance of which geometric figure is parked can be obtained by
comparing the area occupied by a square of side 1.0 to the area of a
disk of diameter 1.0. The ratio of the areas, disk to square, is π/4.
Therefore, it would be anticipated that more disks could be placed in
a box than squares in the same number of tries.
And the Intel doc:
The test assumes a next random point (x, y) successfully ”parked”, if
it is far enough from every previous successfully ”parked” point. The
sufficient distance between the points (x1, y1) and (x2, y2) is
min(|x1 - x2|,|y1 - y2|) > 1.
I'm guessing that the π/4 disk to square ratio and the differences between how many discs can fit vs squares might be why you're seeing a different number. (although right now I fail to see a directly relationship between 3523 and 3070 and π/4. 3523 * π/4 = 2767, which is close, but I'm sure if there's a relationship it's slightly more complex than just simple multiplication.)
Not a great answer, but my best guess.
EDIT: Interestingly enough, I did a quick implementation using discs with 1 unit diameter and getting results around 4000 parked. So maybe there's a bit more to this than my untrained self can grasp (or maybe .NET's Random doesn't pass the test?) Anyway, here's my disc implementation:
List<Point> parkedCars = new List<Point>();
Random random = new Random();
void Main()
{
int parked = 0;
for (int i = 0; i < 12000; i++)
{
double x = random.NextDouble() * 100;
double y = random.NextDouble() * 100;
Point pointToPark = new Point(x, y);
if (IsSafeToPark(pointToPark))
{
parkedCars.Add(pointToPark);
parked++;
}
}
Console.WriteLine("Parked: " + parked);
}
private bool IsSafeToPark(Point pointToPark)
{
//make sure it's "inside" the box
if (pointToPark.X < 0.5 || pointToPark.X > 99.5
|| pointToPark.Y < 0.5 || pointToPark.Y > 99.5)
return false;
if (parkedCars.Any(p => Distance(pointToPark, p) <= 1))
return false;
return true;
}
private double Distance(Point p1, Point p2)
{
return Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
}
Using my likely too simple application of the π/4 ratio yields about 3142. A bit closer, but it seems very incorrect.
EDIT: As #mike z pointed out, my test using directly distance is incorrect. According to the parameters of the test, which I forgot about, just checks that the X and Y distance are greater than 1. Changing my Distance check to:
Math.Max(Math.Abs(p1.X - p2.X), Math.Abs(p1.Y - p2.Y))
Yields a much closer result around 3450, which is pretty close. If I take out my "//make sure it's "inside" the box" check, averaged over 10 tries gets 3531!
So my final, "working" code is:
public struct Point
{
public double X,Y;
public Point(double x, double y)
{
this.X = x;
this.Y = y;
}
}
List<Point> parkedCars = new List<Point>();
Random random = new Random();
void Main()
{
int parked = 0;
for (int i = 0; i < 12000; i++)
{
double x = random.NextDouble() * 100;
double y = random.NextDouble() * 100;
Point pointToPark = new Point(x, y);
if (IsSafeToPark(pointToPark))
{
parkedCars.Add(pointToPark);
parked++;
}
}
Console.WriteLine("Parked: " + parked);
}
private bool IsSafeToPark(Point pointToPark)
{
if (parkedCars.Any(p => Distance(pointToPark, p) <= 1))
return false;
return true;
}
private double Distance(Point p1, Point p2)
{
return Math.Max(Math.Abs(p1.X - p2.X), Math.Abs(p1.Y - p2.Y));
}
EDIT: I ran the test 100 times twice, and averaged the results to 3521.29 and 3526.74 respectively. Not sure if this means there still something slightly more to this, but perhaps this is just indicative of rounding or floating point precision differences between .NET and Fortran.
Below I have a method I search from the internet to calculate the percentrank function of Excel in C#. I modify a bit to suit my program but didn't change the main logic.
The program compiles and runs fine without any error (that I am aware of). However further checking my code, in my main, I call the function using
double result = percentRank( array, x);
where
x is an int
array is a List (int)
It is of a different type than what percentRank method is specified to take, but it still runs fine. My question is WHY?
private static double percentRank(List<int> array, double x)
{
// Calculate the PERCENTRANK(array, x)
//If X matches one of the values in the array, this function is
//equivalent to the Excel formula =(RANK(x)-1)/(N-1) where N is the number of data points.
//If X does not match one of the values, then the PERCENTRANK function interpolates.
// http://www.pcreview.co.uk/forums/algorithm-computing-excel-percentrank-t946312.html
array.Sort();
double result = 0;
bool foundX = false;
for (int index = 0; index < array.Count; index++)
{
if (array[index] == x)
{
result = ((double)index) / ((double)array.Count - 1);
foundX = true;
break;
}
}
// calculate value using linear interpolation
if (foundX == false)
{
double x1, x2, y1, y2;
x1 = x2 = x;
for (int i = 0; i < array.Count - 1; i++)
{
if (array[i] < x && x < array[i + 1])
{
x1 = array[i];
x2 = array[i + 1];
foundX = true;
break;
}
}
if (foundX == true)
{
y1 = percentRank(array, x1);
y2 = percentRank(array, x2);
result = (((x2 - x) * y1 + (x - x1) * y2)) / (x2 - x1);
}
else
{
// use the smallest or largest value in the set which ever is closer to valueX
if (array[0] > x)
{
result = 0;
}
else
{
result = 1;
}
}
}
return result;
}
EDIT: OK the answer is implicit type conversion. Can I disable it? I don't like it because it may generate some bugs that I am not aware of.
My question is WHY?
You can assign an integer to a double value. C# will implicitly convert from Int32 to Double.
You can see this here:
double value = 3;
This is allowed because of the same implicit conversion. Without that conversion, you would have to type:
double value = 3.0;
This is specified in the C# Language Specification, section "6.1.2 Implicit numeric conversions"
The implicit numeric conversions are:
...
From int to long, float, double, or decimal.
The C# compiler is performing an implicit cast operation. A double can hold any integer value.
There is an implicit conversion from int to double.
The conversion is implicit because a double can hold the value of an int without losing accuracy.
There is an explicit conversion from double to int, but no implicit conversion. The reason being, if you store a double in an int, there is going to be a loss of value when it cuts off the decimal places.
MSDN has a good writeup about conversions: http://msdn.microsoft.com/en-us/library/ms173105.aspx
An int can be implicitly cast to a double. That's what's happening here.