Vincent Cheung

Vincent Cheung's Blog

« Newer Post Home Older Post »

Monday, August 02, 2004

Converting Java to C#

I've been converting some of my Java code to C# lately. Btw, I've been using SharpDevelop as my IDE. It's basically a GNU version of Visual Studio. It's pretty good and the price is right :). It lets you compile .NET right away (no need to download the IDE or anything) and lets you compile right from the IDE.

The syntax in C# is remarkably similar to that of Java.

In most cases, the majority of the conversion involves capitalizing methods (such as main() to Main(), Math.log to Math.Log, and x.length to x.Length). The other major part is that C#'s math class doesn't have random numbers built-in, so you have to use the Random class. The bad thing is that the Random class doesn't generate normally distributed random numbers. I had to write a class to convert uniform random numbers to Gaussian. I used the polar form of the Box-Muller transformation:

double x1, x2, w, y1, y2;

do {

x1 = 2.0 * rand.NextDouble() - 1.0;
x2 = 2.0 * rand.NextDouble() - 1.0;
w = x1 * x1 + x2 * x2;

} while(w >= 1.0);

w = Math.Sqrt(-2.0 * Math.Log(w) / w);

// two Gaussian random numbers are generated
y1 = x1 * w;
y2 = x2 * w;

I rand this a number of times and checked it out in Matlab. Mean and variance were about right and a qqplot was spot on, except for the ends which were a little off, but that's alright.

I first used this other technique whereby the central limit theorem is used to generate the numbers. The sum of uniformly distributed random numbers is normally distributed. So you can sum 10 of these numbers, then normalize it to mean 0 and standard deviation 1, since the mean of the sum is the #rand * 0.5 and standard deviation is sqrt(#rand / 12).


Plus, the constants for Double.MAX_VALUE in Java is now Double.MaxValue. "final" is "const".


The biggest problem is arrays. While C# supports jagged arrays, Java-style, you cannot instanciate their size all in one shot, i.e. you can't do this:
double[][] x = new double[3][5];

You have to do this:
double[][] x = new double[3][];
for(int i = 0; i < x.length; i++)
x[i] = new double[5];

Now this is a BIG problem for me, cuz I need to declare A LOT of matrices and this is a big pain in the ass. Especially when you have to declare say a 5 dimensional array!

C# also supports "true" multidimensional arrays:
double[,] x = new double[3, 5];

I read somewhere that they were slower, but Microsoft was gonna fix that. Well, this solves my problem, except that now all the matrix indexing in my Java code won't work in C#. That's not too bad, cuz I can do a find and replace (find "][", replace with ", ", then find ", ]" and replace with ",]"). The bigger problem is that since it's no longer an array of array objects per se, you can't just go x.Length (total number of elements in the array) and x[0].Length (not allowed), you have to go x.GetLength(0) and x.GetLength(1). So, more find and replaces - starting with the largest, find "[0][0][0].Length" and replace with ".GetLength(3)", then find "[0][0].Length" and replace with ".GetLength(2)", etc. The problem is that when you get to .Length, you don't really want to replace with .GetLength(0), cuz arrays can just use .Length, which imho is nicer cuz it's more Java-like. Eh, I think it still works.

This whole array stuff buggers up the fact that I wanted the C# code to be basically identical to the Java code....

Oh, another thing. I like the whole array of array idea, cuz when dealing with videos, if I have an array, I can have the first index represent time and the last three represent a single frame in the video, so it's easy to just take the reference to the last three dimensions and write that 3D matrix to an image file or use that to just represent an image, i.e. I changed my Epitome code so that images can be treated as videos transparently cuz it's easy to wrap in image into a 4D matrix and then just strip out the first "frame" of the resulting epitome as that is it's image epitome. But, with these multidimensional arrays, that's no longer possible, and it's too much effort and not nice to have to declare the jagged arrays using a for loop....

So, in order to do this wrapping, I'll have to explicitly make a copy of the last three dimensions to rip out a frame from the "video".


Also, in Java you can do this:
int[][] patchSize = new int[][] {{16, 16}, {8, 8}, {4, 4}, {2, 2}};

But you have to do one of the following in C#:
int[][] patchSize = new int[][] {new int[] {16, 16}, new int[] {8, 8}, new int[] {4, 4}, new int[] {2, 2}};
int[][] patchSize = {new int[] {16, 16}, new int[] {8, 8}, new int[] {4, 4}, new int[] {2, 2}};
int[,] patchSize = {{16, 16}, {8, 8}, {4, 4}, {2, 2}};

The instanciation of jagged arrays is just not as nice as in Java.


But overall, these differences are quite minor cuz all the for loops and declarations, etc. can all remain the same. I haven't done much of a comparison between Java and C#, but it seems faster than my previous results with Java. I'm guessing that it runs in 3/4 or 1/2 the time. Not bad for such as easy port. I might end up just coding in C# cuz it's so similar to Java. I tried porting to C++ last week sometime, but realized that multidimensional arrays in C++ was a pain in the ass. I believe that when passing arrays to functions, the array size had to be fixed! (at least for the dimensions other than the first one). I guess this could be remedied by having the array as a member of a class and the methods would just access that, but it's too much effort......C# is easier :p, but may be slower cuz of the whole CLI thing with .NET.

0 Comments:

Post a Comment