只使用乘法和整数,如何进行'除'一个数字

Using only Multiplication and Integers, how can I 'divide' a number?

本文关键字:数字 一个 何进行 整数      更新时间:2023-09-26

问题:

我在rapidweaver中用于构建堆栈的API不允许除法或浮点数,但我基本上想用一个数字除以另一个数字。

API的相关规则:

API放在html、css和javascript文件中,并在生成项目文件之前编译成实际的html、css和javascript。

  1. 在这个API中,每个数学运算都包装在:

    %( math )%

  2. 所以要达到(1 + 3)* 6,它将是:

    %( %( 1 + 3 )% * 6 )%

    使用%( 1 + 3 * 6 )%会破坏它,每个%()%内部只允许一个操作。

  3. 另外,我可以使用变量来表示用户输入

    %id=variableName%

  4. 所以,如果我想将用户输入乘以2,我可以这样做:

    %( %id=variableName% * 2 )%

我想做的:

%( %id=CB_seconds% / 2 )% OR %( %id=CB_seconds% * 0.5 )%

但是因为一些愚蠢的原因^这些^是不允许的…

我想取用户输入%id=CB_seconds%,并将其分成两半。用户将%id=CB_seconds%定义为0到10,000之间的整数。我需要原始值和不同区域的分割值。一种可能的解决方案是让用户指定一个介于0到5000之间的值,并将该值乘以2。然而,这不起作用,因为用户正在定义动画的长度,要求他们指定他们真正想要的长度的一半是令人困惑的。

我的问题

是否有一些方法可以只使用整数和乘法/加法/减法,而不知道之前的数字是什么?


这是堆栈API的文档- https://yourhead.tenderapp.com/kb/stacks-api/templates

如果您只访问+*,这是不可能的。

这是数学:

如果你有一个只使用加法和乘法的函数,如:

a/b=f(a,b)

你可以把f展开成一个多项式函数。

如果n趋于无穷

您将拥有f(n,n)=n/n=1

但是多项式总是趋向于+∞,-∞或0,所以这样的函数不可能存在

您可以将乘法定义为一系列加法,您也可以将除法定义为一系列减法。为此,您需要循环和比较功能。要将a除以b,假设两者都是整数并且a > b,您的伪代码将是:

division = 1
c = a - b
while (c > b)
  c = c - b
  division = division + 1
end while

在这一点上,你有a / b = division,剩下的是c

例如,a = 10b = 3:

division = 1
c = 10 - 3 = 7
c (=7) > 3 --> Continue
  c = 7 - 3 = 4
  division = 2
c (= 4) > 3 --> Continue
  c = 4 - 3 = 1
  division =  3
c (= 1) < 3 --> Stop

此时division = 3c = 1,即10 / 3 = 3 (+ 1)

我看到堆栈API允许比较。如果它也包含循环,那么你可以实现上面的。

说了这么多,他们居然没有部门,真是太蠢了。

我知道这是非常糟糕的编码,但你可以将每个数字从1加倍到5000,看看它是否是用作输入的数字(也检查它是否是数字+1,以查看四舍五入分数)。因为它只有5000个操作,所以它应该不会对性能产生太大影响。

新答案

因为我们没有真正的循环,所以我们必须实现一个二分查找。我们要做的是:

CB_copy = CB_seconds;
CB_half = 0;
for ( exp = 13 ; exp > 0 ; exp- - ) {
    if ( CB_copy > 1 << exp ) {
        CB_half += 1 << (exp-1);
        CB_copy -= 1 << exp;
    }
}

但是我们没有条件句。我们可以用已有的比较来重写它:

CB_copy = CB_seconds;
CB_half = 0;
for ( exp = 13 ; exp > 0 ; exp- - ) {
    CB_half += ( 1 << (exp-1) ) * ( CB_copy > 1 << exp );
    CB_copy -= ( 1 << exp ) * ( CB_copy > 1 << exp )
}
如前所述,我们没有循环。所以我们必须展开所有内容,并得到28行代码:
CB_copy = CB_seconds;
CB_half = 0;
CB_half += ( 1 << 12 ) * ( CB_copy > 1 << 13 );
CB_copy -= ( 1 << 13 ) * ( CB_copy > 1 << 13 );
CB_half += ( 1 << 11 ) * ( CB_copy > 1 << 12 );
CB_copy -= ( 1 << 12 ) * ( CB_copy > 1 << 12 );
. . .
CB_half += ( 1 << 1 ) * ( CB_copy > 1 << 2 );
CB_copy -= ( 1 << 2 ) * ( CB_copy > 1 << 2 );
CB_half += ( 1 << 0 ) * ( CB_copy > 1 << 1 );
CB_copy -= ( 1 << 1 ) * ( CB_copy > 1 << 1 );

我们也没有位移位。但我们可以从自定义列表中获取值。因此,将1 << k替换为twoExp{k},为k的14个值,并在您的plist中设置这些常量:

CB_half += ( twoExp12 ) * ( CB_copy > twoExp13 );
CB_copy -= ( twoExp13 ) * ( CB_copy > twoExp13 );
etc

最后,将其转换为正确的语法:

%CB_copy = %id=CB_seconds% %
%CB_half = 0%
%CB_half = %( CB_half + %( twoExp12 * %( CB_copy > twoExp13 )% )% )% %
%CB_copy = %( CB_copy - %( twoExp13 * %( CB_copy > twoExp13 )% )% )% %
. . .
%CB_half = %( CB_half + %( twoExp0 * %( CB_copy > twoExp1 )% )% )% %
%CB_copy = %( CB_copy - %( twoExp1 * %( CB_copy > twoExp1 )% )% )% %

28行代码除以2。好运。


老回答

我们可以实现GrimRepear1908的想法,循环到5000,并检查加倍是否得到正确的值。在真实的语言中,我们要做的是:

for repeatIndex in (0..5001):
  CB_half += repeatIndex*( repeatIndex*2==CB_seconds || repeatIndex*2==CB_seconds+1 )

使用API,似乎只有当您将每行操作保持为一个操作时,代码才可读,因此这变成:

for repeatIndex in (0..5001):
  doubled = repeatIndex*2
  doubledLessOne = doubled-1
  CB_evenTarget = doubled==CB_seconds
  CB_oddTarget = doubledLessOne==CB_second
  isTarget = CB_evenTarget || CB_oddTarget // is 0 or 1
  multed = repeatIndex * isTarget
  CB_half = multed + CB_half

在该语言的语法中(假设我正确地完成了变量赋值),您最终得到:

%[repeat 5001]%
%doubled = %( %id=repeatIndex% *2 )% %
%doubledLessOne = %( %id=doubled% -1 )%
%CB_evenTarget = %( %id=doubled% == %id=CB_seconds% )%
%CB_oddTarget = %( %id=doubledLessOne% == %id=CB_second% )%
%isTarget = %( %id=CB_evenTarget% || %id=CB_oddTarget% )%
%multed = %( %id=repeatIndex% * %id=isTarget% )%
%CB_half = %( %id=multed% + %id=CB_half% )%
%[endrepeat]%

Nuclearman提出了一种二分搜索技术。这可能会使代码更短,但考虑到简单循环最终带来的痛苦,我不打算尝试。

相关文章: