Нарисуйте строку с нормализованной научной нотацией (надписью) - PullRequest
1 голос
/ 25 февраля 2012

Я хочу нарисовать следующую строку в моей игре

Для сравнения, во Вселенной 10 ^ 75 частиц.

, где 10 75 отформатировано в нормализованной научной записи (как мы делали в школе).

Я использую метод SpriteBatch.DrawString, но не могу найти конечного решения. Есть несколько тривиальных:

  • Нарисуйте две строки, в которых вторая строка имеет меньший шрифт или масштабируется.
  • Нарисуйте изображение.

Я просматривал таблицы UTF, но, похоже, это невозможно.

Должен ли я иметь специальный шрифт для этой задачи?

Ответы [ 2 ]

3 голосов
/ 25 февраля 2012

Я не знаком с 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}}}x10{{1}}", 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();
    }

Так что теперь вы сможете использовать FormatAsPowerOfTen(123400, 2), в результате чего 1.23x10⁵.

0 голосов
/ 15 марта 2015

Я подправил ответ @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();
    }

Также обратите внимание, что из-за замены шрифта этот метод может дать вам ужасные результаты для комбинаций 1,2 и 3 с другими цифрами в показателе . 0 и 4-9 были добавлены в юникоде и отсутствуют во многих шрифтах. Убедитесь, что вы используете шрифт, который поддерживает все цифры, например Arial Unicode MS, Cambria, Calibri, Consolas или Lucida Sans Unicode.

...