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;
}
为什么会得到这样的结果,你已经得到答案了。在这里,我将更详细地描述我在评论中所写的内容。
您的问题可以(我认为应该)通过数学方法解决,无需将数字转换为字符串,也无需一堆
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 suffixes = new[] { "K", "M", "B", "T", "Qa", "Qi" };,然后我们通过索引取出必要的名称,例如像这样:(suffixes[exponent - 1]索引从 0 开始)。格式——您可以按照自己的方式来“粘合”线条,但我会做类似这样的事情
$"{scaled:0.#}{suffix}"。这使用带有数字格式的字符串插值。结果是1,2M整个最终的代码将会是这样的:
这里没有检查,因为如果数字更高
Qi或更低K(例如1),它就会下降,我的任务只是展示原理,然后根据需要扭曲它。现在我们来谈谈便利性。我现在要从 Unity 中进行抽象,因为我要使用 Unity 没有的语言的现代方面,但最后我会告诉你如何解决这个问题。
通常,为了解决此类问题,我们会编写扩展特定类型并可以在任何地方调用的扩展方法。实际上,让我们创建这样一种方法,甚至使它通用,以便它适合任何数字类型。
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}"; например),这样会更紧凑、更容易理解)。使用方式如下:
简单测试:
让我们看看这里发生了什么。在第一种情况下,执行以下代码分支:
让我们看一下前两个术语:
text[0]- 这是符号的类型char、值、代码'1'49text[1]- 这是符号的类型char、值、代码'0'48当这两个值相加时,它们恰好就是与字符代码相等的数字,而结果是……一个数字
97!接下来是添加一行。此时97它会被转换成一个字符串"97",然后进行通常的字符串连接,无论右边添加了什么。这是以一种基本的方式“治愈”的 - 我们只需开始用一个空字符串形成一个变量,然后所有内容立即转换为字符串并以通常的方式连接起来:
但最好使用现代字符串插值,那么肯定不会有任何意外,一切都会按照您指定的方式严格替换和格式化:
有了结构,为空闲游戏写出这些超大数字就容易多了。
如果
Number超过 100,则将数字除以 10,然后ZeroCount相反增加。最奇妙的是,你可以
+为-这个结构编写数学运算。要获取后缀,只需
ZeroCount / 3获取后缀数组中的索引即可,不需要百层索引switch。这样做是为了方便超载ToString()。如果数字实在太离谱,
ZeroCount可以将其改为long。如果您需要更精确地添加小数字,Number您可以将其更改为double。