RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1607270
Accepted
Reik
Reik
Asked:2025-02-20 04:27:31 +0000 UTC2025-02-20 04:27:31 +0000 UTC 2025-02-20 04:27:31 +0000 UTC

C# 字符串变量的字符输出无法正常进行

  • 772

c# 为什么我输入10000时下面的脚本输出97.0K? 100000 时是 145K 吗?

private string Output(int value)
{
        string text, lasttext = "";
        text = value.ToString();
        switch (text.Length)
        {
            case int n when n <= 3:
                lasttext = "";
                return text;
            case int n when n > 3 && n <= 6:
                lasttext = "K";
                break;
            case int n when n > 6 && n <= 9:
                lasttext = "M";
                break;
            case int n when n > 9 && n <= 12:
                lasttext = "B";
                break;
            case int n when n > 12 && n <= 15:
                lasttext = "T";
                break;
            case int n when n > 15 && n <= 18:
                lasttext = "Q";
                break;
        }
        switch (text.Length % 3)
        {
            case 1:
                text = text[0] + "," + text[1] + text[2] + lasttext;
                break;
            case 2:
                text = text[0] + text[1] + "," + text[2] + lasttext;
                break;
            case 0:
                text = text[0] + text[1] + text[2] + lasttext;
                break;
        }
        return text;
    }
c#
  • 3 3 个回答
  • 104 Views

3 个回答

  • Voted
  1. Best Answer
    EvgeniyZ
    2025-02-21T01:16:14Z2025-02-21T01:16:14Z

    为什么会得到这样的结果,你已经得到答案了。在这里,我将更详细地描述我在评论中所写的内容。

    您的问题可以(我认为应该)通过数学方法解决,无需将数字转换为字符串,也无需一堆if和switch,只需几行代码和相当简单的计算。

    看,这里有一个数字1 234 567,正如你所看到的,这些数字以 3 个数字为一组,通过这个数字你可以理解,如果有一组,那么这些就是“千”,如果有两组,那么就已经是数百万、三十亿,等等。为了从数学上计算这种优度,对数会非常有用,或者更准确地说log10。如果我们使用它,我们将看到下面的图片:log10(1) = 0,,log10(12) = 1......log10(123) = 2正如你所看到的,这给了我们第一个数字之后的数字的数量,这正是我们需要的。现在我们将这个数字除以 3 ( log10(1000) = 3) 并得到组数 ( log10(1 000)/3 = 1, log10(1 000 000)/3 = 2, log10(1 000 000 000)/3 = 3)。更准确地说,这就是我们找到数字顺序的方法。

    现在让我们把这个数字变得更紧凑(缩放数字),也就是说,如果这个数字是1 234 567,那么我们知道以戈比计算它是 100 万,或者更准确地说,是1,2。为了将这个数字缩小到这个程度,我们需要将其除以之前得到的 1000 的幂,结果得到如下结果:1 234 567/1000^2 = 1,234567

    这就是全部的数学运算,正如你所见,一切都非常简单。现在我们用 C# 来编写它。
    所有的数学都在类中Math,从中我们需要方法Log10和提升幂的方法(Pow)。然后我们得到如下代码:

    var number = 1_234_567;
    var exponent = (int)Math.Log10(number) / 3;     //2
    var scaled = number / Math.Pow(1000, exponent); // 1.234567
    

    我们已经掌握了基础知识,剩下的就是形成所需的类型,或者更准确地说,“剪切”数字并添加后缀(末尾的字母)。

    • 后缀 - 有了后缀,一切都变得极其简单。我们将所有必要的名称制作成一个数组,例如var suffixes = new[] { "K", "M", "B", "T", "Qa", "Qi" };,然后我们通过索引取出必要的名称,例如像这样:(suffixes[exponent - 1]索引从 0 开始)。

    • 格式——您可以按照自己的方式来“粘合”线条,但我会做类似这样的事情$"{scaled:0.#}{suffix}"。这使用带有数字格式的字符串插值。结果是1,2M

    整个最终的代码将会是这样的:

    var number = 1_234_567;
    var exponent = (int)Math.Log10(number) / 3;
    var scaled = number / Math.Pow(1000, exponent);
    var suffixes = new[] { "K", "M", "B", "T", "Qa", "Qi" };
    var suffix = suffixes[exponent - 1];
    var result = $"{scaled:0.#}{suffix}";
    

    这里没有检查,因为如果数字更高Qi或更低K(例如1),它就会下降,我的任务只是展示原理,然后根据需要扭曲它。


    现在我们来谈谈便利性。我现在要从 Unity 中进行抽象,因为我要使用 Unity 没有的语言的现代方面,但最后我会告诉你如何解决这个问题。

    通常,为了解决此类问题,我们会编写扩展特定类型并可以在任何地方调用的扩展方法。实际上,让我们创建这样一种方法,甚至使它通用,以便它适合任何数字类型。

    public static class FormatExtensions
    {
        public static string ToHuman<T>(this T number) where T : INumber<T>
        {
            var doubleValue = double.CreateChecked(number);
            var suffixes = new[] { "K", "M", "B", "T", "Qa", "Qi" };
            var exponent = doubleValue < 1000 ? 0 : (int)(Math.Log10(doubleValue) / 3);
            var divisor = Math.Pow(1000, exponent);
            return exponent == 0
                ? doubleValue.ToString("0.#") // Число меньше 1000
                : exponent - 1 < suffixes.Length
                    ? $"{doubleValue / divisor:0.#}{suffixes[exponent - 1]}"
                    : $"{doubleValue / Math.Pow(1000, suffixes.Length):0.#}{suffixes[^1]}"; // Вышли за пределы массива суффиксов
        }
    }
    
    • T- 这是一种通用类型,它允许您不受某件事物的束缚。
    • this T- 通过它this我们得到一个可以应用该方法的特定值。
    • where T : INumber<T>- 在.NET 7中出现了这个接口,它由所有标准数字类型实现。在早期版本中您可以尝试在此处设置IComparable。
    • CreateChecked()- 也是 .NET 7 的一项创新。该方法从 创建一个特定类型(在我们的例子中为double,以便不会丢失小数部分(如果有))INumber<>。在早期版本中,您可以尝试使用Convert.ToDouble()。
    • doubleValue < 1000 ? 0- 这里有一个检查,如果数字小于 1000,那么我们返回 0,由此我们进一步了解到添加后缀和其他小工具是没有意义的。
    • exponent - 1 < suffixes.Length- 我们不允许超出后缀数组的长度。
    • $"{doubleValue / Math.Pow(1000, suffixes.Length):0.#}{suffixes[^1]}";- 如果没有合适的后缀,那么我们将数字缩放到最后一个可用的数字并输出它。 (对我来说,这里最好使用科学计数法($"{doubleValue:e2}"; например),这样会更紧凑、更容易理解)。

    使用方式如下:

    var result = 1_234_567.ToHuman(); // "1,2M"
    

    简单测试:

    1.ToHuman();                // 1
    1_000.ToHuman();            // 1K
    1_000_000.ToHuman();        // 1M
    1_000_000_000.ToHuman();    // 1B
    1.281.ToHuman();            // 1,3
    572_353.286.ToHuman();      // 572,4K
    1_751.92f.ToHuman();        // 1,8K
    74_626_224L.ToHuman();      // 74,6M
    int.MaxValue.ToHuman();     // 2,1B
    double.MaxValue.ToHuman();  // 1797693134862320000000000000000000000000000000000000..(куча нулей)..Qi ... (нет подходящего суффикса в массиве)
    float.MaxValue.ToHuman();   // 340282346638529000000Qi (нет подходящего суффикса в массиве)
    long.MaxValue.ToHuman();    // 9,2Qi
    
    • 2
  2. CrazyElf
    2025-02-20T15:27:22Z2025-02-20T15:27:22Z

    让我们看看这里发生了什么。在第一种情况下,执行以下代码分支:

    case 2:
        text = text[0] + text[1] + "," + text[2] + lasttext;
               ^^^^^^^^^^^^^^^^^
        // 97,0K
    

    让我们看一下前两个术语:

    • text[0]- 这是符号的类型char、值、代码'1'49
    • text[1]- 这是符号的类型char、值、代码'0'48

    当这两个值相加时,它们恰好就是与字符代码相等的数字,而结果是……一个数字97!接下来是添加一行。此时97它会被转换成一个字符串"97",然后进行通常的字符串连接,无论右边添加了什么。

    这是以一种基本的方式“治愈”的 - 我们只需开始用一个空字符串形成一个变量,然后所有内容立即转换为字符串并以通常的方式连接起来:

        text = "" + text[0] + text[1] + "," + text[2] + lasttext;
               ^^^^^
        // 10,0K
    

    但最好使用现代字符串插值,那么肯定不会有任何意外,一切都会按照您指定的方式严格替换和格式化:

        text = $"{text[0]}{text[1]},{text[2]}{lasttext}";
        // 10,0K
    
    • 1
  3. Yaroslav
    2025-02-20T14:18:30Z2025-02-20T14:18:30Z

    有了结构,为空闲游戏写出这些超大数字就容易多了。

    [Serializable]
    public struct BigNumber
    {
        public float Number;
        public int ZeroCount;
    
        ...
    }
    

    如果Number超过 100,则将数字除以 10,然后ZeroCount相反增加。

    ...
    
    public BigNumber (float number, int zeroCount) 
    {
        Number = number;
        ZeroCount = zeroCount;
        Optimize();
    }
    
    private void Optimize () 
    {
        if (Number > 1000) 
        {
            Number /= 10f;
            ZeroCount++;
            Optimize();
        } 
        else if (Number < 100 && zeroCount > 0)
        {
            Number *= 10f;
            ZeroCount--;
            Optimize();
        }
    }
    

    最奇妙的是,你可以+为-这个结构编写数学运算。

    ...
    
    public static BigNumber operator + (BigNumber a, BigNumber b)
    {
        if (a.ZeroCount == b.ZeroCount)
        {
            return new BigNumber(a.Number + b.Number, a.ZeroCount);
        } 
        else if (a.ZeroCount > b.ZeroCount)
        {
            int zeroDelta = a.ZeroCount - b.ZeroCount;
            if (zeroDelta > 6)
                return a; // b much less
            int ANumber = a.ZeroCount * 10f * zeroDelta;
            return new BigNumber(ANumber * b.Number, b.ZeroCount);
        }
        else
        {
            return b + a;
        }
    }
    
    public static BigNumber operator - (BigNumber a, BigNumber b)
    {
        ...
    }
    

    要获取后缀,只需ZeroCount / 3获取后缀数组中的索引即可,不需要百层索引switch。这样做是为了方便超载ToString()。

    private const string[] Suffix = new[] {"", "k", "m", "t" ...};
    ...
    
    public override string ToString () 
    {
        int dIndex = ZeroCount / 3;
        string suffix = Suffix[dIndex];
        return Number.ToString("F2") + suffix;
    }
    

    如果数字实在太离谱,ZeroCount可以将其改为long。如果您需要更精确地添加小数字,Number您可以将其更改为double。

    • 0

相关问题

  • 使用嵌套类导出 xml 文件

  • 分层数据模板 [WPF]

  • 如何在 WPF 中为 ListView 手动创建列?

  • 在 2D 空间中,Collider 2D 挂在玩家身上,它对敌人的重量相同,我需要它这样当它们碰撞时,它们不会飞向不同的方向。统一

  • 如何在 c# 中使用 python 神经网络来创建语音合成?

  • 如何知道类中的方法是否属于接口?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5