2个数字之间的差异
Posted
技术标签:
【中文标题】2个数字之间的差异【英文标题】:Difference between 2 numbers 【发布时间】:2008-12-04 09:06:29 【问题描述】:我需要完美的算法或 C# 函数来计算 2 个十进制数之间的差异(距离)。
例如:100 和 25 之间的区别是 75100 和-25 是 125-100 和 -115 是 15-500 和 100 是 600
是否有一个 C# 函数或一个非常优雅的算法来计算这个,或者我必须用 ifs 分别处理每个案例。
如果有这样的函数或算法,是哪一个?
【问题讨论】:
您给出的示例都是整数 - 您测试的所有数字都是这种情况还是一些浮点数?如果是这样,那么您可能必须满足于测试它们何时“足够接近” - 即检查差异是否小于某个阈值。 为什么投反对票?对于不熟悉 Math.Abs 的人来说,这似乎是一个公平的问题 +1,不需要对一个完全没问题的问题投反对票 我认为短语'或者我必须用ifs单独处理每个案例。'清楚地表明这个问题是用 chhek 语言问的 【参考方案1】:你可以这样做
public decimal FindDifference(decimal nr1, decimal nr2)
return Math.Abs(nr1 - nr2);
【讨论】:
当然没有必要把这段代码放到一个单独的函数中,但更多的是为了澄清(nr1 - nr2) = Int32.MinValue
时崩溃 - 问题here
@cz 崩溃对于Int32.MinValue
来说非常明显。正如here 所述,发生这种情况的原因非常简单。数字数据类型的范围总是像-x
到(x-1)
。当然,如果我尝试在相同的数据类型中容纳+x
(Int32.MinValue
的绝对值)来获得绝对值,那么它必然会失败:)【参考方案2】:
result = Math.Abs(value1 - value2);
【讨论】:
他想说数学。 Math 是 .Net 类,其中包含三角函数、对数函数和其他常见数学函数的静态方法 :p 不敢相信有人花了 2 年的时间来接我:) 特别小心:当value1-value2
等于Int32.MinValue
时,由于System.OverflowException
异常,此代码将崩溃。更多详情here.
反击自己 - Int32.MinValue
的崩溃非常明显。正如here 所述,发生这种情况的原因非常简单。数字数据类型的范围总是像-x
到(x-1)
。当然,如果我尝试在相同的数据类型中容纳+x
(Int32.MinValue
的绝对值)来获得绝对值,那么它必然会失败。
有符号整数范围的端点是“减一”(例如,16 位为 -32,768 和 32,767)【参考方案3】:
只是添加这个,因为这里没有人写它:
虽然你肯定可以使用
Math.Abs(number1 - number2);
这是最简单的解决方案(也是公认的答案),我想知道没有人写出 Abs 的实际作用。这是一个适用于Java、C、C# 和其他所有具有类似 C 语法的语言的解决方案:
int result = number1 - number2;
if (result < 0)
result *= -1;
就这么简单。你也可以这样写:
int result = number1 > number2 ? number1 - number2 : number2 - number1;
最后一个编译后可能会更快;两者都有一个 if 和一个减法,但在某些情况下第一个有一个乘法,最后一个没有。为什么只在某些情况下?一些 CPU 具有“交换符号”操作,编译器识别 *= -1
所做的事情,它只是交换符号,因此它会为提供它的 CPU 发出交换符号操作,而不是乘法,并且此操作与一个 CPU 操作可以获得(通常是一个时钟周期)。
第一个代码示例实际上是在做 Abs 在大多数实现中所做的事情,以在支持的情况下使用“交换符号”,最后一个代码示例在没有“交换符号”的 CPU 上会更快,并且乘法比添加(在现代 CPU 上,它们通常同样快)。
【讨论】:
我很惊讶没有人说过这不适用于所有整数。我确定 int.MaxValue 和 int.MinValue 之间的区别不是 -1 @Aelphaeis 你的编辑是假的;除非您完全理解某个主题,否则请不要编辑帖子。当然,它适用于负整数。例如。number1
是 100
和 number2
是 -100
: 100 - (-100) = 200
这是正确的。或者看到这个(-50) - (-80) = 30
,也是正确的。它不适用于int.MaxValue
和int.MinValue
的原因是因为这两者之间的区别是4'294'967'295
,但适合int
的最大数字是2'147'483'647
,因此你会导致它溢出两次。
我已经意识到这一点,并且实际上进行了第二次编辑。我猜它从未被批准。
使用result = -result
而不是result *= -1
。毕竟,这就是 -
(否定)运算符的用途。
真的,谢谢@Mecki,我需要那个公式。【参考方案4】:
我认为这在 C# 中是不可能的,您可能需要考虑在 Assembler 中实现它
【讨论】:
不了解此解决方案背后数学原理的人不一定会知道它是否可行,尤其是当他们有可行的替代方案时。在这种情况下,不可能察觉到枯燥的幽默,所以投反对票是完全合理的。有趣与否,这是错误的信息。 使用这就是我在企业项目中的做法:
namespace Extensions
public class Functions
public static T Difference<T>(object x1, object x2) where T : IConvertible
decimal d1 = decimal.Parse(x1.ToString());
decimal d2 = decimal.Parse(x2.ToString());
return (T)Convert.ChangeType(Math.Abs(d1-d2), typeof(T));
和测试:
namespace MixedTests
[TestClass]
public class ExtensionsTests
[TestMethod]
public void Difference_int_Test()
int res2 = Functions.Difference<int>(5, 7);
int res3 = Functions.Difference<int>(-3, 0);
int res6 = Functions.Difference<int>(-3, -9);
int res8 = Functions.Difference<int>(3, -5);
Assert.AreEqual(19, res2 + res3 + res6 + res8);
[TestMethod]
public void Difference_float_Test()
float res2_1 = Functions.Difference<float>(5.1, 7.2);
float res3_1 = Functions.Difference<float>(-3.1, 0);
double res5_9 = Functions.Difference<double>(-3.1, -9);
decimal res8_3 = Functions.Difference<decimal>(3.1, -5.2);
Assert.AreEqual((float)2.1, res2_1);
Assert.AreEqual((float)3.1, res3_1);
Assert.AreEqual(5.9, res5_9);
Assert.AreEqual((decimal)8.3, res8_3);
【讨论】:
ToString() 是昂贵的,因为它是一个 int 或 float 你正在处理。以上是关于2个数字之间的差异的主要内容,如果未能解决你的问题,请参考以下文章
如何将一个集合分成两个子集,以使两个集合中数字之和之间的差异最小?
如何在 PHP 中比较和获取 2 个 multidim 数组之间的差异