2个数字之间的差异


69

我需要完美的算法或C#函数来计算2个十进制数字之间的差异(距离)。

例如:
10025之间的差是75
100,-25125
-100-11515
-500,100600

是否有C#函数或非常优雅的算法来计算此值,否则我必须分别使用if s处理每种情况。

如果有这样的功能或算法,那是哪一个呢?


您提供的示例都是整数-是您测试的所有数字的大小写还是某种浮点数?如果是这样,那么您可能必须在它们“足够接近”时进行测试,即检查差异是否小于某个阈值。
Geoglyph

4
为什么投票?对于不熟悉Math.Abs​​的人来说,这似乎是一个公平的问题
annakata

+1,无需
否决

我认为这句话“或者我必须与ifs分开处理每个案件”。清楚地显示出,这一问题被问chhek舌头
johnc

Answers:


118

你可以这样

public decimal FindDifference(decimal nr1, decimal nr2)
{
  return Math.Abs(nr1 - nr2);
}

5
当然,无需将此代码放到单独的函数中,但更多是为了澄清
terjetyl

4
何时崩溃(nr1 - nr2) = Int32.MinValue-这里的
cz

@cz崩溃对于很明显Int32.MinValue。提到为什么出现这种情况的原因是很琐碎这里。数的数据类型的范围是总喜欢-x(x-1)。当然,如果我尝试在相同的数据类型中容纳+x(的绝对值Int32.MinValue)以获得绝对值,那么它必然会失败:)
RBT

32
result = Math.Abs(value1 - value2);

他想说数学。数学是.Net类,其中包含用于三角函数,对数函数和其他常见数学函数的静态方法
Germstorm

1
:p简直不敢相信有人花了两年时间来接我:)
马丁2010年

1
格外注意该代码value1-value2Int32.MinValue由于System.OverflowException异常而等于时将崩溃。更多细节在这里
RBT

反抗我自己-崩溃显然很明显Int32.MinValue。提到为什么出现这种情况的原因是很琐碎这里。数的数据类型的范围是总喜欢-x(x-1)。当然,如果我尝试在同一数据类型中容纳+x(的绝对值Int32.MinValue)来获取绝对值,那么它必然会失败。
RBT

符号整数范围的端点为“ off by one”(例如,对于16位,为-32,768和32,767)
Scott Weaver

27

只需添加它,就像这里没有人写的那样:

虽然您可以肯定地使用

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 2014年

2
@Aelphaeis您的编辑是虚假的;除非您完全理解主题,否则请勿编辑帖子。当然,它对于负整数也可以正常工作。例如,number1100number2-100100 - (-100) = 200这是正确的。或查看this (-50) - (-80) = 30,这也是正确的。为什么它不工作的原因int.MaxValueint.MinValue是因为这两个之间的差异4'294'967'295,但数量最多,适合到int2'147'483'647这样的话你使其溢出两次。
梅基2014年

我意识到了这一点,实际上进行了第二次编辑。我想它从未被批准过。
Aelphaeis 2014年

1
使用result = -result代替result *= -1-毕竟,这是(负)运算符的作用。
David R Tribble

真的,谢谢您的@Mecki,我需要该公式。
yusf

5

我认为在C#中是不可能的,您可能需要考虑在Assembler中实现它


2
不知道该解决方案背后的数学原理的人不一定会知道是否可能,尤其是当他们有可行的替代方案时。在这种情况下,干humor的幽默是无法检测到的,因此,低票是完全合理的。有趣与否,这是错误的信息。
JoeBloggs

使用<humor> </ humor>或一个;)
Ape-in​​ago

最初的问题带有一个标签,上面写着需要幽默感。在这种情况下,所有有趣的答案都是允许的!
拉瑟五世卡尔森

1
在这里检测干燥的幽默并非没有可能。来“汇编器”吗?在任何折磨的道路上发出邀请显然是程序员的机智。但是我同意一些标记或表情符号总是有帮助的。
斯通蒂普'17

@LasseVågsætherKarlsen,不过,公平地说,发布此答案的用户是在问题中编辑该标签的人,而不是OP
jrh

1

这就是我在企业项目中做的事情:

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);

        }
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.