带标准化科学记数法(上标)的抽绳

时间:2012-02-25 07:37:02

标签: c# string silverlight xna utf

我想在游戏中绘制以下字符串

  

要进行比较,宇宙中有10 ^ 75个粒子。

其中10 75 采用标准化的科学记数法格式化(正如我们在学校所做的那样)。

我使用SpriteBatch.DrawString方法,但我无法找出一个解决方案。有一些微不足道的:

  • 绘制两个字符串,其中第二个字符串的字体较小或缩放。
  • 画一幅图像。

我一直在看UTF表,但似乎不可能。

我必须为此任务使用特殊字体吗?

2 个答案:

答案 0 :(得分:3)

我不熟悉XNA,但在Silverlight项目中,我必须做同样的事情,我最终用上标字符构建科学记数字。

您不需要特殊字体,只需要一个Unicode字体,其中包含下面使用的上标字符。

下面是将数字0-9映射到相应字符的代码:

    private static string GetSuperscript(int digit)
    {
        switch (digit)
        {
            case 0:
                return "\x2070";

            case 1:
                return "\x00B9";

            case 2:
                return "\x00B2";

            case 3:
                return "\x00B3";

            case 4:
                return "\x2074";

            case 5:
                return "\x2075";

            case 6:
                return "\x2076";

            case 7:
                return "\x2077";

            case 8:
                return "\x2078";

            case 9:
                return "\x2079";

            default:
                return string.Empty;
        }
    }

这会将您的原始双重转换为科学记数法

    public static string FormatAsPowerOfTen(double? value, int decimals)
    {
        if(!value.HasValue)
        {
            return string.Empty;
        }

        var exp = (int)Math.Log10(value.Value);

        var fmt = string.Format("{{0:F{0}}}x10FormatAsPowerOfTen(123400, 2)", decimals);

        return string.Format(fmt, value / Math.Pow(10, exp), FormatExponentWithSuperscript(exp));
    }

    private static string FormatExponentWithSuperscript(int exp)
    {
        var sb = new StringBuilder();

        bool isNegative = false;

        if(exp < 0)
        {
            isNegative = true;
            exp = -exp;
        }

        while (exp != 0)
        {
            sb.Insert(0, GetSuperscript(exp%10));

            exp = exp/10;
        }

        if(isNegative)
        {
            sb.Insert(0, "-");
        }

        return sb.ToString();
    }

现在,您应该可以使用1.23x10⁵生成{{1}}。

答案 1 :(得分:0)

我在某些地方调整了@Phil的答案,并希望与您分享我的版本。

    public static string FormatAsPowerOfTen(this double? value, int decimals)
    {
        if (!value.HasValue)
            return string.Empty;
        else
            return FormatAsPowerOfTen(value.Value, decimals);
    }

    public static string FormatAsPowerOfTen(this double value, int decimals)
    {
        const string Mantissa = "{{0:F{0}}}";

        // Use Floor to round negative numbers so, that the number will have one digit before the decimal separator, rather than none.
        var exp = Convert.ToInt32(Math.Floor(Math.Log10(value)));

        string fmt = string.Format(Mantissa, decimals);

        // Do not show 10^0, as this is not commonly used in scientific publications.
        if (exp != 0)
             fmt = string.Concat(fmt, " × 10{1}"); // Use unicode multiplication sign, rather than x.

        return string.Format(fmt, value / Math.Pow(10, exp), FormatExponentWithSuperscript(exp));
    }

    private static string FormatExponentWithSuperscript(int exp)
    {
        bool isNegative = false;
        var sb = new StringBuilder();

        if (exp < 0)
        {
            isNegative = true;
            exp = -exp;
        }

        while (exp != 0)
        {
            sb.Insert(0, GetSuperscript(exp % 10));
            exp = exp / 10;
        }

        if (isNegative)
            sb.Insert(0, '⁻'); //Use unicode SUPERSCRIPT minus

        return sb.ToString();
    }

另请注意,由于字体替换,此方法可能会为您提供ugly results for combinations of 1,2 and 3 with other digits in an exponent。 0和4-9以unicode添加,并且从许多字体中丢失。您应确保使用支持所有数字的字体,如Arial Unicode MS,Cambria,Calibri,Consolas或Lucida Sans Unicode。