在一个不同的SO问题中,要求它获得一个有符号整数以数字方式反转: 123变成321并且-123变成-321
这是一个显而易见的,易读的实现:
int reverse (int i) {
int sign = i/Math.Abs(i);
var abs = string.Concat(Math.Abs(i).ToString().Reverse());
return int.Parse(abs)*sign;
}
还建议使用这种更紧凑的LINQ表达式:.ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');
但我不理解后者的结果:
int j = -123;
int a = j.ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');
int b = -(123.ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0'));
int c = -123.ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');
int d = -(123).ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');
Console.WriteLine($"{a} , {b} , {c} , {d}");
结果
3207 , -321 , -321 , -321
为什么它仅适用于文字整数? 我的谬论是什么,我会错误地认为什么?
答案 0 :(得分:3)
使用a
时,您将从-123
开始,而使用其他123
时,您得到的结果是-
。
(-123)
包围123 检查一下。
using System;
using System.Linq;
public class Program
{
public static void Main()
{
int j = -123;
int a = j.ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');
int b = -(123.ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0'));
int c = -123.ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');
int d = -(123).ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');
//Make -123 like line below.
int e = (-123).ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');
Console.WriteLine($"{a} , {b} , {c} , {d}, {e}");
Console.ReadKey();
}
}
//OUTPUTS
//3207 , -321 , -321 , -321, 3207
我在上面回答了为什么使用该方法无法获得正确的结果,但是我没有回答如何实现。现在我同意你的看法。 “对此没有很好的LINQ表达式”。然而;我能够将其转换为易于阅读的一行代码,成为美观的扩展方法。
我确实查看了问题下方的评论,并且从Falco Alexander的评论中借用了Math.Sign
这个我不知道确实存在的功能。我本来是要通过if x < 0 return result * -1
排序手动完成的。
我还注意到当前使用的Aggregate
函数存在一个问题,那就是它不支持小数。目前只有int
,但我想起来了,并尝试了double
。要添加小数点,我汇总了string
;但是后来我认为聚合字符串是一件坏事,因为我们只想尽可能少地执行字符串计算,而只是做了一个new string
(这打破了内联LINQ的外观,但我认为它要好得多)。我最后得到的是您在下面看到的内容,与您所拥有的几乎相同,但是使用的是负数和小数。
using System;
using System.Linq;
public class Program
{
public static void Main()
{
int j = -123;
int k = 123;
double l = -123.456;
double m = 123.456;
Console.WriteLine(j.Reverse());
Console.WriteLine(k.Reverse());
Console.WriteLine(l.Reverse());
Console.WriteLine(m.Reverse());
Console.ReadKey();
}
}
public static class Extensions
{
public static int Reverse(this int value)
{
return Math.Sign(value) * int.Parse(new string(Math.Abs(value).ToString().Reverse().ToArray()));
}
public static double Reverse(this double value)
{
return Math.Sign(value) * double.Parse(new string(Math.Abs(value).ToString().Reverse().ToArray()));
}
}
//OUTPUTS
//-321
//321
//-654.321
//654.321
答案 1 :(得分:3)
原因是,在所有情况下,除了a
之外,转换为int
的{{1}}都是“ 123”而不是“ -123”。负号应用于执行结果,而不在string
调用中使用
在此表达式中:
.ToString
-123.ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0')
将在“ 123”上调用,然后其余的LINQ查询通过Aggregate返回.ToString()
来执行,然后减号将应用于结果int数。一个例子是
int
即使这个表达式:
-1 * 123.ToString().Reverse().Aggregate(...)
将被转换为类似的内容:
int d = -(123).ToString().Reverse().Aggregate(0, (y, x) => 10 * y + x - '0');
首先编译器删除多余的括号,然后执行表达式,最后将结果的符号更改为负
P.S。
正如@PetSerAI正确指出的那样,您可以修改LINQ表达式以使其工作如下:
int d = -1 * (123).someExpr