【问题标题】:Difference between 2 numbers2个数字之间的差异
【发布时间】:2008-12-04 09:06:29
【问题描述】:

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

例如:
10025 之间的区别是 75
100-25125
-100-11515-500100600

是否有一个 C# 函数或一个非常优雅的算法来计算这个,或者我必须用 ifs 分别处理每个案例。

如果有这样的函数或算法,是哪一个?

【问题讨论】:

  • 您给出的示例都是整数 - 您测试的所有数字都是这种情况还是一些浮点数?如果是这样,那么您可能必须满足于测试它们何时“足够接近” - 即检查差异是否小于某个阈值。
  • 为什么投反对票?对于不熟悉 Math.Abs​​ 的人来说,这似乎是一个公平的问题
  • +1,不需要对一个完全没问题的问题投反对票
  • 我认为短语'或者我必须用ifs单独处理每个案例。'清楚地表明这个问题是用 chhek 语言问的

标签: c# algorithm math numbers


【解决方案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)。当然,如果我尝试在相同的数据类型中容纳+xInt32.MinValue 的绝对值)来获得绝对值,那么它必然会失败:)
【解决方案2】:
result = Math.Abs(value1 - value2);

【讨论】:

  • 他想说数学。 Math 是 .Net 类,其中包含三角函数、对数函数和其他常见数学函数的静态方法
  • :p 不敢相信有人花了 2 年的时间来接我:)
  • 特别小心value1-value2 等于Int32.MinValue 时,由于System.OverflowException 异常,此代码将崩溃。更多详情here.
  • 反击自己 - Int32.MinValue 的崩溃非常明显。正如here 所述,发生这种情况的原因非常简单。数字数据类型的范围总是像-x(x-1)。当然,如果我尝试在相同的数据类型中容纳+xInt32.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 你的编辑是假的;除非您完全理解某个主题,否则请不要编辑帖子。当然,它适用于负整数。例如。 number1100number2-100: 100 - (-100) = 200 这是正确的。或者看到这个(-50) - (-80) = 30,也是正确的。它不适用于int.MaxValueint.MinValue 的原因是因为这两者之间的区别是4'294'967'295,但适合int 的最大数字是2'147'483'647,因此你会导致它溢出两次。
  • 我已经意识到这一点,并且实际上进行了第二次编辑。我猜它从未被批准。
  • 使用result = -result 而不是result *= -1。毕竟,这就是 -(否定)运算符的用途。
  • 真的,谢谢@Mecki,我需要那个公式。
【解决方案4】:

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

【讨论】:

  • 不了解此解决方案背后数学原理的人不一定会知道它是否可行,尤其是当他们有可行的替代方案时。在这种情况下,不可能察觉到枯燥的幽默,所以投反对票是完全合理的。有趣与否,这是错误的信息。
  • 使用 或 ;)
  • 原始问题的标签表示需要幽默感。在这种情况下,所有有趣的答案都是允许的!
  • 在这里发现枯燥的幽默并非不可能。来吧“汇编”?任何酷刑之路的邀请显然都是程序员的智慧。但我同意一些标记或表情符号总是有帮助的。
  • @LasseVågsætherKarlsen 不过,公平地说,发布此答案的用户是将该标签编辑到问题中的用户,而不是 OP
【解决方案5】:

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

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 你正在处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-15
  • 1970-01-01
  • 1970-01-01
  • 2017-05-31
相关资源
最近更新 更多