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

本文关键字:复合 添加 百分比 金额 删除 编程 方式 | 更新日期: 2023-09-27 17:51:26

有人给我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;
}
}

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

可以将其视为一个操作列表,每个操作还提供了如何撤销自身的详细信息。大约…

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表达式,表示给定当前"累加器"(acc)和序列中的当前项(o),返回o.Apply(acc)的函数。"种子"值(100m)用作第一个acc,然后函数的返回值作为acc传递给下一个o,依此类推。