如何以编程方式从值中删除/添加复合/非复合百分比和固定金额?

时间:2011-04-21 00:12:39

标签: c# algorithm

我获得100美元,并告诉我必须按顺序对其进行以下操作:

添加97
添加5
乘以3%的复合利息

基本上,它变为(100 + 97 + 5)* 1.3 = 208.06

现在这就是我的问题,我知道要从208.06回到100,我必须这样做:

208.06 / 1.3 - (97 + 5)= 100

上面是一个简单的例子,但是一旦我开始混合化合物,非复合,平量,并且不仅能够添加,而且减去这些值,它变得非常复杂。例如,如果我再次获得100美元,并告诉我必须按顺序应用以下调整,我不知道如何扭转它:

1)加入化合物3%
2)加入化合物4%
3)减去90
4)减3 5)加入3%的非化合物 6)加入4%的非化合物

上述计算如下:

((100 *(1.03)*(1.04)) - 90 - 3)*(1 + 0.04 + 0.03)

对于上述情况,我不知道如何通过了解后期调整后的值以及添加的6项调整来实现逆转。

上面的公式可以简化为,这样可以更容易地看到如何反转它:

(100 * 1.03 * (1.04)) - 93 + 7 = 21.21 and to reverse it, we just do:

(100 * 1.03 * (1.04)) - 93 + 7 = 100

我的问题是如何循环并以正确的顺序应用操作。我是否必须将操作顺序及其金额存储在一个类中,然后通过每次计算进行预测?

我已经在Math.StackExchange.com上发布了这个,但他们认为它是一个很大的公式,并且从编程的角度来看,我不需要理解,我需要遍历每个调整并将其从总计中删除。这基本上是我坚持的,但我不清楚如何通过循环每个调整来解决它,因为重要的是我以正确的顺序应用调整。我并不是在寻找一个解决方案,但更多的是朝着正确的方向发展。

这是一个实现。应用它似乎适用于初始样本,但如果我做我的另一个,它似乎不起作用,除非我做错了什么:

void Main()
{
var ops = new List<Operation>
{

new CompoundInterest(3.0m),
new CompoundInterest(4.0m),
new Subtract(90.0m),
new Subtract(3.0m),
new NoncompoundInterest(3.0m),
new NoncompoundInterest(4.0m)
};

var applied = ops.Aggregate(100m, (acc, o) => o.Apply(acc));

var unapplied = ops.Reverse().Aggregate(applied, (acc, o) => o.Unapply(acc));

}

// Define other methods and classes here
abstract class Operation
{
public abstract decimal Apply(decimal value);
public abstract decimal Unapply(decimal value);
}
class CompoundInterest : Operation
{
public decimal percent {get;set;}
public CompoundInterest(decimal percent)
{
    this.percent = percent;
}

public override decimal Apply(decimal value)
{
    return value * (1m + percent/100m);
}

public override decimal Unapply(decimal value)
{

    return value / (1m + percent/100m);
}
}
class NoncompoundInterest : Operation { 
public decimal percent {get;set;}
public NoncompoundInterest(decimal percent)
{
    this.percent = percent;
}


public override decimal Apply(decimal value)
{
    return value * (percent/100m);
}

public override decimal Unapply(decimal value)
{
    return value / (percent/100m);
}
}

class Add : Operation { 
public decimal amount {get;set;}
public Add(decimal amount)
{
    this.amount = amount;
}


public override decimal Apply(decimal value)
{
    return value + amount;
}

public override decimal Unapply(decimal value)
{
    return value - amount;
}

}

class Subtract : Operation { 
public decimal amount {get;set;}
public Subtract(decimal amount)
{
    this.amount = amount;
}


public override decimal Apply(decimal value)
{
    return value - amount;
}

public override decimal Unapply(decimal value)
{
    return value + amount;
}
}

1 个答案:

答案 0 :(得分:1)

考虑到这一点的一种方法是作为操作列表,每个操作还提供了如何撤消自身的详细信息。大致...

abstract class Operation
{
    public abstract decimal Apply(decimal value);
    public abstract decimal Unapply(decimal value);
}

class CompoundInterest : Operation
{
    public CompoundInterest(decimal percent)
    {
        this.percent = percent;
    }

    public override decimal Apply(decimal value)
    {
        return value * (1m + percent/100m);
    }

    public override decimal Unapply(decimal value)
    {
        return value / (1m + percent/100m);
    }
}

class NoncompoundInterest : Operation { ... }

class Add : Operation { ... }

class Subtract : Operation { ... }

现在,您可以在列表中表示您的操作链:

var ops = new List<Operation>
{
    new Add(97m),
    new Add(5m),
    new CompoundInterest(3.0m),
};

var applied = ops.Aggregate(100m, (acc, o) => o.Apply(acc));
var unapplied = ops.Reverse().Aggregate(208.06m, (acc, o) => o.Unapply(acc));

更新: Aggregate()的工作原理如下:

decimal acc = 100m;
foreach(Operation o in ops)
    acc = o.Apply(acc);
decimal applied = acc;

(acc, o) => o.Apply(acc)是一个lambda表达式,表示在给定当前“累加器”(o.Apply(acc))和序列中的当前项(acc)的情况下返回o的函数。 “种子”值(100m)用作第一个acc,然后函数的返回值将作为acc传递给下一个o,依此类推。