Examples of C# source code
Here I have collected some snippets to give a small flavour of the sort of code
you will see on this site. These are taken from non-trivial programs so they
might not make complete sense on their own. For more information or to see
the full code, please visit each application's home page.
- Performing RSA encryption and decryption
- Computing 'true anomaly' for an elliptical orbit
- Creating a Mandelbrot set bitmap image
Performing RSA encryption and decryption
(from
RSA with BigInts)
This code echoes the famous 1977 RSA Challenge, by generating an RSA key pair based
on two large primes (the same primes used in the Challenge) and using this key pair
to encrypt and decrypt a message. The process requires my
BigInt
class for performing arithmetic on arbitrarily large integers (since the numbers
used here are too large for the Pentium's built-in functions). Notice that,
thanks to the C# operators defined by BigInt, the code looks pretty much the same
as it would if we were using regular 32-bit integers!
public static
void DoDemo()
{
BigInt
p = "398075086424064937397125500550386491199064362342526708406385189575946388957261768583317";
BigInt
q = "472772146107435302536223071973048224632914695302097116459852171130520711256363590397527";
BigInt
d, e, n;
GenerateKeyPair(p,
q, out d, out
e, out n);
Console.WriteLine("public key
is ({0}, {1})", d, n);
Console.WriteLine("private key
is ({0}, {1})", e, n);
Console.WriteLine();
//Encode the message "MAGIC SQUEAMISH"
// using A=01, B=02, Z=26, etc
BigInt
msg = "130107090319172105011309198";
Console.WriteLine("plaintext
is {0}", msg);
BigInt
encryptedMsg = BigInt.modpower(msg, d, n);
Console.WriteLine("plaintext
encrypted using public key: {0} -> {1}",
msg, encryptedMsg);
Console.WriteLine("cyphertext
decrypted using private key: {0} -> {1}",
encryptedMsg, BigInt.modpower(encryptedMsg, e, n));
}
public static
void GenerateKeyPair(BigInt p, BigInt q, out
BigInt d,
out BigInt e, out BigInt n)
{
d = 0;
e = 0;
ushort c = 0, testLimit;
BigInt
r;
bool done;
n = p
* q;
BigInt
phiN = (p-1) * (q-1);
done
= false;
do
{
c++;
r = phiN.ShortMultiply(c) + 1;
testLimit = 500;
for(d
= 3; d < testLimit && (r % d != 0); d += 2);
if(d
< testLimit)
{
e = r / d;
if(!( (d % phiN) == (e % phiN) ))
done = true;
}
} while(!done);
}
Computing 'true anomaly' for an elliptical orbit
(from the
Hohmann Transfer Orbit
demo)
This routine is used by the EllipticalOrbitingBody class to calculate
the angle (in radians) between the body and the sun. It solves Kepler’s equation
(using Newton-Raphson iteration) to get the body’s ‘eccentric anomaly’, E, which
is then used to get the angle.
Kepler’s equation, M = E - e sin(E), relates the ‘mean anomaly’ to
the ‘eccentric anomaly’ for a body in an elliptical orbit. The mean anomaly can
be thought of as the body’s progress through its orbital period (so if the body
has an orbital period of one year and is six months into its orbit then its mean
anomaly is π radians; ie half of the total). The eccentric anomaly takes into
account Kepler’s law about sweeping out equal areas in equal time (so the body goes
faster when closer to the sun). It can be used to compute the exact position in
an elliptical orbit of eccentricity e.
Given M and e, we want to solve Kepler’s equation for E. However, the equation is
transcendental so we must use non-algebraic techniques to solve it. The demo uses
Newton-Raphson iteration. We rewrite the equation as
f(E) = E - e sin(E) – M
and differentiate with respect to E:
f’(E) = 1 - e cos(E)
Now to solve f(E) = 0 using Newton-Raphson we iterate
Xn+1 = Xn - [ f(Xn)
/ f’(Xn) ]
i.e. En+1
= En - [ (En
- e sin(En) - M) / (1 – e cos(En))
]
until |En+1 - En|
is less than some small amount.
public override
double GetTrueAnomaly()
{
double ecc = eccentricity;
double
M = base.GetTrueAnomaly();
// the base implementation returns the
// "mean anomaly", which
assumes a circular orbit.
// The rest of our work involves
// correcting
this to get the true "eccentric" anomaly
double E, E_new, E_old = M + (ecc / 2);
const
double epsilon = 0.0001;
double
bodyAngle;
//Solve [ 0 = E - e sin(E) - M ] for E using Newton-Raphson:
// Xn+1 = Xn - [ f(Xn) / f'(Xn)
]
// E
= Eccentric Anomaly, M = Mean Anomaly
do
{
E_new = E_old - (E_old - ecc * Math.Sin(E_old)
- M)
/
(1 - ecc * Math.Cos(E_old));
E_old = E_new;
} while(Math.Abs(E_old
- E_new) > epsilon);
E = E_new;
//Solve cos(bodyAngle) = ( cos(E) - e ) / (1 - e cos(E) ) to
get the
// body's angle with the Sun
bodyAngle
= Math.Acos( (Math.Cos(E)
- ecc)/(1 - ecc * Math.Cos(E)) );
// Arccos returns a value between 0 and π, but when M >
π (ie
// past halfway point) we
// take (2π - angle) to get the solution that lies between
π and 2π
int T = OrbitalPeriod, t = GetDaysElapsed() % T;
if(t > T / 2)
bodyAngle = 2.0F *
Math.PI - bodyAngle;
return bodyAngle;
}
Creating a Mandelbrot set bitmap image
(from the
Mandelbrot Set Viewer demo)
This routine is used in MainForm to create the main display bitmap
(basically a grey-scale representation of the various values returned by MandelbrotSet.IsInSet()).
It computes the complex number represented by each pixel in the bitmap, and converts
each complex number's "Mandelbrot value" to a shade of grey, which is then set as
the colour of the corresponding pixel. It also handles the updating of the
display and the progress bar and aborts on user cancellation.
private void CreateMandelbrotImage(int imageWidth, int
imageHeight,
int maxIterations, ToolStripProgressBar
progressBar)
{
int x, y, numIterations;
double a, b;
int greyScale;
Color pixelColor;
//Create a new bitmap and fill it with the window's background
// colour (white) to ensure that it
// has no transparency even if
the user cancels the rendering.
bmpMandSet
= new Bitmap(imageWidth,
imageHeight);
Graphics rbGraphics = Graphics.FromImage(bmpMandSet);
rbGraphics.Clear(this.BackColor);
rbGraphics.Dispose();
for (y = 0, b = viewManager.YtoB(0, imageHeight);
y < imageHeight
&& isDrawing;
y++, b -= viewManager.UnitsPerPixelY)
{
for (x = 0, a = viewManager.XtoA(0);
x < imageWidth
&& isDrawing;
x++, a+= viewManager.UnitsPerPixelX)
{
//Count the number of iterations before the
Mandelbrot
// function becomes unbounded
numIterations = MandelbrotSet.IsInSet(a,
b, maxIterations);
if (numIterations == maxIterations)
// we never saw |z| > 2; colour the pixel black
bmpMandSet.SetPixel(x, y, Color.Black);
else
if (numIterations < maxIterations)
{
//Colour the pixel grey, as a
percentage of maxIterations
// (larger number of iterations = darker grey)
greyScale = (int)(255.0
*
((double)(maxIterations -
numIterations)
/ (double)maxIterations));
pixelColor = Color.FromArgb(greyScale,
greyScale, greyScale);
bmpMandSet.SetPixel(x, y, pixelColor);
}
}
if ((y % 10 == 0) && isDrawing)
{
//We've calculated another 10 rows; show the
latest
// bitmap and update the progress bar.
this.Refresh();
progressBar.Value = y;
}
//DoEvents() allows the user to cancel the drawing
part-way through.
Application.DoEvents();
}
}