Try this out. I haven't tested it, but it should be more or less correct.
public string ToSI(double d, string format = null)
{
char[] incPrefixes = new[] { 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' };
char[] decPrefixes = new[] { 'm', '\u03bc', 'n', 'p', 'f', 'a', 'z', 'y' };
int degree = (int)Math.Floor(Math.Log10(Math.Abs(d)) / 3);
double scaled = d * Math.Pow(1000, -degree);
char? prefix = null;
switch (Math.Sign(degree))
{
case 1: prefix = incPrefixes[degree - 1]; break;
case -1: prefix = decPrefixes[-degree - 1]; break;
}
return scaled.ToString(format) + prefix;
}