如何将2个受限制的十进制变量转换为第三个变量,反之亦然?

时间:2011-11-02 18:47:19

标签: c# algorithm decimal rounding

我有2种转换器方法如下:

private const decimal MaxValidValue = 99.99m;
public decimal ConvertABToC(decimal a, decimal b)
{
    return a * b;
}

public void ConvertCtoAB(decimal c, ref decimal a, ref decimal b)
{
    if (c > MaxValidValue*MaxValidValue)
    {
        throw new ApplicationException();
    }

    if (c <= MaxValidValue)
    {
        a = 1.00m;
        b = c;
    }
    else 
    {
        // need to introduce some logic or assumptions here
    }
}

有三件重要的事情要知道:

1)a和b变量的范围为0.00到99.99,因此c的值不能大于99.99 * 99.99

2)a,b和c的小数进动不得超过2小时,例如a = 99.123无效。

3)你可以使用舍入,只要你需要十进制.Round(a * b,2)== c。

4)如(1,3),(3,1),(2,2),(1,4),(0.5,8)或偶数(0.25,16)的组合都是有效的;只要c是a和b的乘积就没关系。

您将如何完成ConvertCtoAB的实施?

非常感谢,

3 个答案:

答案 0 :(得分:2)

C乘以10,000。然后将这个数字计入其主要因素。然后找到素数因子的分区为两组,使得每组中数字的乘积小于10,000。如果可以找到这样的分区,则将这两个产品除以100 AB。否则,请在号码中添加一个,然后重试。

例如,如果C=100.07,则因子为2, 2, 5, 5, 10007。由于其中一个产品必须包含因子10007,这是一个素数,因此永远不能满足第一个条件。所以我们再次尝试使用1000701 = 3*3*3*13*2851。这一次,我们可以对数字进行分区,我们将A=3.51B=28.51作为可能的解决方案。

你最多可以做99次。如果您需要100或更多,则无法从ConvertABToC生成输入值。

这只能保证ConvertCtoAB的结果反馈到ConvertABtoC时会生成相同的C,而不是相反。{{1}}它似乎违反了规则#3,但其他地方的问题是关于四舍五入。

如果根本不允许进行舍入,则应在尝试原始10000 * C后停止并报告不可行性。

答案 1 :(得分:1)

我删除了之前的答案,因为我认为它不再有用,因为随着时间的推移,这个问题发生了很大的变化。

以下是我理解的问题:

您将获得c类型的输入(decimal),以便:

  • 0 <= c <= 99.99m * 99.99m
  • c最多包含两位小数(即c == decimal.Round(c, 2)

您需要找到decimalab,以便:{/ p>

  • ab中的每一个都在[0, 99.99m]
  • 范围内
  • ab各占最多两位小数
  • decimal.Round(a * b, 2) == c

我的回答是c的所有值都不能 。反例:c = 9997.50

ab的最高可能值(每个99.99米)会产生decimal.Round(a * b, 2) == 9998.00,因此产品太高会失败。

现在,如果你保持a尽可能高,并尽可能减少b,我们会得到a=99.99m, b=99.98m - 现在decimal.Round(a * b, 2) == 9997.00,这样就失败了产品太低了。

无法在这两个值之间获取任何产品 - 我们以尽可能少的数量扰乱了我们的第一次尝试。因此,ab没有满足此问题的值。

(我期待引入一条新的规则来解决这个问题,因为这似乎是这个问题的方式......)

答案 2 :(得分:0)

Skeet将区间视为自身* 100的想法使得一切都变得更加清晰......

问题确实没有完整的解决方案。它要求你创建一个双射函数f:A x B - &gt; C,
其中A = B = {0 ... 9999}且C = {0 ... 9999 * 9999}

9999 * 9999 = 9998001;再加上0,它的基数为99,980,002。

A X B的基数为100,000,000。

当域和codomain具有不同的基数时,无法定义有限集上的双射函数。总共最多有19,998个c值,其(a,b)分解将有多个解决方案。

回到原始区间定义:最接近正确功能的是:

public decimal Ab2C(decimal a, decimal b)
{
    if(a != 99.99 and a != 99.98)
        return a*100 + b;
    return (100-a)*100 + b; // for instance;
}

在这种情况下,0.02到99.97之间的值将给出独特的结果; a = 0.00或99.99将是相同的,同样对于a = 0.01或99.98。这两个值之间没有任何可能的区别。

public void C2AB(decimal c, out decimal a, out decimal b)
{
    // todo: sanity checks.
    if (c <= 99.99)  // either a = 0.00, or a = 99.99; and b = c.
    {
        b = c;
        a = 0.00;
        return;
    }

    if (c <= 2*99.99)
    {
        b = c - 99.99;
        a = 0.01; // or 9.98.
        return;
    }
    a = c / 100;
    b = c % 100;
}

}