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

发布于 2024-12-13 08:42:39 字数 833 浏览 2 评论 0原文

我有 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
    }
}

有 3 件重要的事情需要知道:

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

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

3)如果您需要,只要decimal.Round(a * b, 2) == c,您就可以使用舍入。

4) 像 (1, 3)、(3, 1)、(2, 2)、(1, 4)、(0.5, 8) 甚至 (0.25, 16) 这样的组合都是有效的;只要 c 是 a 和 b 的乘积就没有关系。

您将如何完成 ConvertCtoAB 的实施?

非常感谢,

I have 2 convertor methods as below:

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
    }
}

There are 3 important things to know:

1) The a and b variables are in the range of 0.00 to 99.99 therefore c can't have a value greater than 99.99*99.99

2) the a, b and c must not have more than 2 decimal precession e.g. a = 99.123 would be invalid.

3) you can use rounding if you'd need to as long as decimal.Round(a * b, 2) == c.

4) combinations like (1, 3), (3, 1), (2, 2), (1, 4), (0.5, 8) or even (0.25, 16) are all valid; it doesn't matter as long as c would be the product of a and b.

How would you complete the implementation of ConvertCtoAB?

Many thanks,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

美煞众生 2024-12-20 08:42:39

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,而不是相反。它似乎违反了规则#3,但其他地方的问题是关于舍入的。

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

Multiply C by 10,000. Then factor this number into its prime factors. Then find a partition of the prime factors into two sets such that the product of the numbers in each set is less than 10,000. If such a partition can be found, then return these two products divided by 100 as A and B. Otherwise, add one to the number and try again.

For example, if C=100.07, then the factors are 2, 2, 5, 5, 10007. Because one of the products must include the factor 10007, which is a prime number, the first condition can never be satisfied. So we try again with 1000701 = 3*3*3*13*2851. This time, we can partition the number, and we have A=3.51 and B=28.51 as a possible solution.

You can do this at most 99 times. If you need 100 or more, than the input value cannot have been generated from ConvertABToC.

This only guarantees that the result of ConvertCtoAB, when fed back into ConvertABtoC will produce the same C, not the other way around. It appears to violate rule #3, but then elsewhere the question is about rounding.

If no rounding at all is allowed, then one should stop and report infeasibility after trying the original 10000*C.

离旧人 2024-12-20 08:42:39

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

这就是我理解的问题:

给你一个decimal类型的输入(c),这样:

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

c 需要找到十进制ab使得:

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

我的答案是仍然不可能适用于c的所有值。反例:c = 9997.50

ab 的最高可能值(各 99.99m)给出 decimal.Round(a * b , 2) == 9998.00,因此产品过高会导致失败。

现在,如果您将 a 保持尽可能高,并尽可能减少 b,我们会得到 a=99.99m, b=99.98m - 现在是 decimal.Round(a * b, 2) == 9997.00,因此结果会因产品太低而失败。

无法获得这两个值之间的任何乘积 - 我们已经对第一次尝试进行了尽可能小的干扰。因此,ab 没有值可以满足问题。

(我预计会引入一项新规则来解决这个问题,因为这似乎就是这个问题的发展方向......)

I've deleted my previous answer, as I don't believe it was helpful any more, as the question's changed so much over time.

Here's what I understand the question to be:

You are given an input (c) of type decimal such that:

  • 0 <= c <= 99.99m * 99.99m
  • c has at most two decimal places (i.e. c == decimal.Round(c, 2))

You are required to find to decimal values a and b such that:

  • Each of a and b are in the range [0, 99.99m]
  • Each of a and b have at most two decimal places
  • decimal.Round(a * b, 2) == c

My answer is that it's still not possible for all values of c. Counterexample: c = 9997.50

The highest possible values of a and b (99.99m each) gives decimal.Round(a * b, 2) == 9998.00, so that fails with a product which is too high.

Now if you keep a as high as it can be, and reduce b as little as possible, we get a=99.99m, b=99.98m - and now decimal.Round(a * b, 2) == 9997.00, so that fails with a product which is too low.

There is no way of getting any product between those two values - we've perturbed our first attempt by as small an amount as possible. Therefore there are no values for a and b satisfying the problem.

(I'm anticipating a new rule being introduced to cope with this, as that seems to be the way this question is going...)

巨坚强 2024-12-20 08:42:39

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

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

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

AXB 的基数为 100,000,000。

当域和余域具有不同的基数时,无法定义有限集上的双射函数。始终最多有 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 值将给出唯一的结果; 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;
}

}

Skeet's idea to treat the interval as itself * 100 makes everything so much clearer...

The problem is indeed without a complete solution. It asks you to create a bijective function f : A x B -> C,
where A = B = {0 ... 9999} and C = {0 ... 9999*9999 }

9999*9999 = 9998001; plus the 0, that gives a cardinality of 99,980,002.

A X B has a cardinality of 100,000,000.

A bijective function over finite sets can't be defined when the domain and codomain have different cardinalities. There will always be at most 19,998 values of c whose (a, b) breakdown will have more than one solution.

Going back on the original interval definition: the closest you can get to a proper function is something like:

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

In this case, values for a between 0.02 to 99.97 will give unique results; a = 0.00 or 99.99 will be identical, likewise for a = 0.01 or 99.98. there is NO possible discrimination between these two values.

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

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文