导出浮点值的整数因子?

时间:2009-08-19 22:19:12

标签: algorithm math

我有一个困难的数学问题,正在打破我的大脑,我的白板和我所有的笔。我正在使用表达2个值的文件,被乘数百分比。这两个值都必须是整数。将这两个值相乘以产生范围。范围是浮点值。

我的用户编辑范围,我必须计算新的百分比和被乘数值。困惑了吗?这是一个例子:

    Multiplicand: 25000 Apples
    Percentage: 400 (This works out to .4% or .004)
    Range: 100.0 Apples (Calculated by Multiplicand * Percentage)

要使事情复杂化,Percentage的允许值为0-100000。 (含义0-100%)Multiplicand是1到32bit int max之间的值(可能是unsigned)。

我需要允许用户输入范围,如下所示:

Range: .04 Apples

并计算适当的百分比和乘数。使用第一个例子:

    OriginalMultiplicand: 25000 Apples
    OriginalPercentage: 400 (This works out to .4% or .004)
    OriginalRange: 100.0 Apples (Calculated by Multiplicand * Percentage)
    NewRange: .01 Apples
    NewPercentage: 40
    NewMultiplicand: 25 Apples

示例计算很简单,所需要的只是通过新旧范围的比例因子调整被乘数和百分比。当用户将值更改为1400.00555时会出现问题。突然间,我没有一个干净的方法来调整这两个值。

我需要一种算法来获取M&的值。 P产生与所需范围最接近的可能值。有什么建议吗?

5 个答案:

答案 0 :(得分:1)

要最大化存储的小数点数,您应使用P为1或0.1%。如果溢出M,则递增P

因此,对于1400.00555的示例,P为1,M为1400006

您的算法将搜索最低的P,以便M不会溢出。你可以在这里进行二元搜索。

public int binarySearch(int P0, int P1) {
   P = (P1 - P0)/2;
   if(P == P0) {
     if(R/(P0/100f) does not overflows 32-bit int) {
       return P0;
     } else {
       return P1;
     }
   }
   if(R/(P/100f) does not overflows 32-bit int) {
     return binarySearch(P0, P);
   } else {
     return binarSearch(P, P1);
   }
}

P = binarySearch(1, 100000);
M = round(R/(P/100f));

答案 1 :(得分:0)

据我通过您的示例了解,您可以代表range 100000 multiplicand * percentage中的multiplicand。任何Multiplicand * Percentage = 100.0 的选择都会给你一个令人满意的百分比值,反之亦然。所以你有两个变量的等式:

Multiplicand

您应该找出另一个等式(约束),以获得特定值Percentage0-100000来解决此等式。否则,您可以选择百分比为Multiplicand之间的任意数字,只需将其替换为第一个等式即可获得range的值。我希望我能正确理解这个问题:)


编辑:好的,那么您应该轻松地对范围进行分解。获取percentage(2-100000),然后尝试通过将范围除以get range; percentage = 2; while(range % percentage != 0) { percentage++; } multiplicand = range / percentage; 来对其进行分解。一旦分裂提醒为零,你就得到了这些因素。这是一个快速的伪代码:

max of percentage = 100000;
max of multiplicand = 4294967295;

Max of range = 4294967295 * 100000 = 429496729500000 (15-digit);

现在你要做的就是计算你的限制:

double

您的最大范围最多包含15位数。大多数编程语言中的doubles数据类型可以代表它。使用Multiplicand & Percentage进行计算,最后将int转换为{{1}}。

答案 2 :(得分:0)

说你有

1) M * P = A

然后你有A的第二个值,所以M和P的新值也可以调用M2,P2和A2:

2) M2 * P2 = A2

这个我不确定,但这就是你似乎在说imho:比例必须保持不变,然后

3) M/P = M2/P2

现在我们有3个方程和2个未知数M2和P2


解决问题的一种方法:

3)变成

M/P = M2/P2
=>M2 = (M/P)*P2

而不是替代2)

(M/P)*P2*P2 = A2
=> P2*P2 = A2 * (P/M)
=> P2 = sqrt(A2 * (P/M))

首先解决P2,然后M2,如果我没有犯任何错误

如果M2和P2必须是整数,则必须进行一些舍入。

编辑:我忘记了整数百分比,所以说

P = percentage/100000 or P*100000 = percentage
P2 = percentage2/100000 or P2*100000 = percentage2

所以只需求解P2和M2,然后将P2乘以100000

答案 3 :(得分:0)

(我在这里遇到了一个糟糕的方法,但我删除了它,因为它很糟糕。)

修改

必须有一种比这更好的方法。让我们重新解释一下这个问题:

你拥有的是一个任意的浮点数。您希望用两个整数表示此浮点数。当乘以一起然后除以100000.0时,整数等于浮点数。唯一的另一个约束是其中一个整数必须等于或小于100000。

很明显,您无法准确地表示浮点数。实际上,即使在“被乘数”中具有无限数量的精度数字,也只能准确表示在1/100000s中可表达的数字。您可以准确地表示333.33333,其中33333333为一个数字,另一个为1;你不能再获得3s。

鉴于此限制,我认为您最好的选择如下:

  1. 将整数格式的浮点数乘以100000,可能是BigNumber的长整数或某些变体。
  2. 因素。记录所有因素。如果将它们存储为2 ^ 3或2 * 2 * 2或什么。
  3. 无关紧要
  4. 抓住尽可能多的因素而不增加它们超过100000.这就成了你的百分比。 (不要试图完美地做到这一点;找到最佳解决方案是NP难问题。)
  5. 取其余因素并将它们相乘。那是你的被子。

答案 4 :(得分:0)

似乎你想选择M和P使得R =(M * P)/ 100000。 所以M * P = 100000 * R,你必须将右边四舍五入为整数。

我将范围乘以100000,然后选择M和P作为结果的因子,这样它们就不会溢出它们允许的范围。