【问题标题】:How can I perform a mathematical calculation on real numbers stored as strings?如何对存储为字符串的实数进行数学计算?
【发布时间】:2016-06-30 17:39:49
【问题描述】:

我有一个类,它包含的值有时是货币值(例如 1.25、2.50、10.00 等),但也可以是字符串“N/A”;因此,它们被声明为字符串:

public class PriceVarianceDataExtended
{
    public String ShortName { get; set; }
    public String ItemCode { get; set; }
    public String Description { get; set; }

    public string Week1PriceCraftworks { get; set; }
    public string Week2PriceCraftworks { get; set; }
    public string VarianceCraftworks { get; set; }

    public string Week1PriceChophouse { get; set; }
    public string Week2PriceChophouse { get; set; }
    public string VarianceChophouse { get; set; }

    public string Week1PriceGordonBiersch { get; set; }
    public string Week2PriceGordonBiersch { get; set; }
    public string VarianceGordonBiersch { get; set; }

    public string Week1PriceOldChicago { get; set; }
    public string Week2PriceOldChicago { get; set; }
    public string VarianceOldChicago { get; set; }

    public string Week1PriceOldChiFranchise { get; set; }
    public string Week2PriceOldChiFranchise { get; set; }
    public string VarianceOldChiFranchise { get; set; }

    public string Week1PriceRockBottom { get; set; }
    public string Week2PriceRockBottom { get; set; }
    public string VarianceRockBottom { get; set; }
}

但是,此代码旨在将货币值(作为字符串)存储在有意义的地方,否则将 val 设置为“N/A”:

private string NOT_APPLICABLE = "N/A";
. . .
if (pvde.Week1PriceCraftworks != NOT_APPLICABLE && 
    pvde.Week2PriceCraftworks != NOT_APPLICABLE)
{
    pvde.VarianceCraftworks = 
        Convert.ToDecimal(pvde.Week2PriceCraftworks) - 
        Convert.ToDecimal(pvde.Week1PriceCraftworks).ToString();
}
else
{
    pvde.VarianceCraftworks = NOT_APPLICABLE;
}

...编译失败,告诉我,“运算符'-'不能应用于'decimal'和'string'类型的操作数”

这就是我的逻辑:

如果输入了“if”块,则表示 Week1PriceCraftworks 和 Week2PriceCraftworks 包含表示为字符串的数值,例如“5.00”和“3.14”

然后,我使用 Convert.ToDecimal() 调用将“5.00”转换为 5,将“3.14”转换为 3.14。这应该产生一个 1.86 的值,然后将其转换为字符串(“1.86”),以便将正确的数据类型分配给 pvde.VarianceCraftworks。

但是,在我看来,这是合理而直接的,我得到了那个错误的消息。我的方法有什么问题?

顺便说一句,“week1”和“week2”的值是通过调用以这种方式结束的方法来设置的:

return price ?? NOT_APPLICABLE;

...所以 Week1PriceCraftworks 和 Week2PriceCraftworks 中包含的内容要么是真实值(存储为字符串)要么是“N/A”。

【问题讨论】:

  • 试试():(Convert.ToDecimal(pvde.Week2PriceCraftworks) - Convert.ToDecimal(pvde.Week1PriceCraftworks)).ToString();
  • 你为什么不简单地使用可空值?
  • @AlexD:这行得通;如果您愿意,可以将其作为答案。
  • @B.ClayShannon 哦,谢谢!它已经被其他人添加了:-)!

标签: c# decimal type-conversion string-math


【解决方案1】:

所以答案就在你的

pvde.VarianceCraftworks = 
        Convert.ToDecimal(pvde.Week2PriceCraftworks) - 
        Convert.ToDecimal(pvde.Week1PriceCraftworks).ToString(); // to string is called during the operation rather than afterwards

其次,我会将您的一些代码移出到扩展方法中:

pvde.Week1PriceCraftworks != NOT_APPLICABLE

到

public static bool HasValue(this string value)
{
    return value != NOT_APPLICABLE;
}

和

Convert.ToDecimal(pvde.Week2PriceCraftworks)

到

public static decimal ToDecimal(this string value)
{
    return Convert.ToDecimal(value);
}

然后它会更好读:

private string NOT_APPLICABLE = "N/A";
. . .
pvde.VarianceCraftworks = NOT_APPLICABLE;
if (pvde.Week1PriceCraftworks.HasValue() && 
    pvde.Week2PriceCraftworks.HasValue())
{
    pvde.VarianceCraftworks = 
        (pvde.Week2PriceCraftworks.ToDecimal() - 
        pvde.Week1PriceCraftworks.ToDecimal()).ToString();
}

如果您选择转到Nullable<T> 等,这也使您能够更改HasValue 的实现。

你甚至可以更进一步,减去两个已知的十进制字符串:

public static string SubtractDecimals(this string value, string subtractValue)
{
    return (value.ToDecimal() - value.ToDecimal()).ToString();
}

那么现在:

private string NOT_APPLICABLE = "N/A";
. . .
pvde.VarianceCraftworks = NOT_APPLICABLE;
if (pvde.Week1PriceCraftworks.HasValue() && 
    pvde.Week2PriceCraftworks.HasValue())
{
    pvde.VarianceCraftworks = pvde.Week2PriceCraftworks.SubtractDecimal(pvde.Week1PriceCraftworks);
}

使用这些扩展方法的好处是您现在可以用简单的英语阅读正在发生的事情,而不必阅读一堆实现细节。如果由于某种原因解决方案无法正常工作,您还可以测试这些单独的扩展方法,以确切了解哪个部分没有按照您的预期工作。

【讨论】:

  • 什么不是?我在脑海中写下了这个
【解决方案2】:

问题是基于括号的优先顺序。由于 ToDecimal().ToString(),它正在评估 Decimal - String。

如果你把它改成下面它应该可以工作

(
  Convert.ToDecimal(pvde.Week2PriceCraftworks) - 
  Convert.ToDecimal(pvde.Week1PriceCraftworks)
).ToString();

【讨论】:

    【解决方案3】:
    pvde.VarianceCraftworks = 
            (Convert.ToDecimal(pvde.Week2PriceCraftworks) - 
            Convert.ToDecimal(pvde.Week1PriceCraftworks)).ToString();
    

    【讨论】:

    • 请添加一些解释为什么此代码有助于 OP。这将有助于为未来的观众提供一个可以学习的答案。请参阅How to Answer 了解更多信息。
    • 但我的回答几乎等于接受
    • 那么就不需要了,可以去掉。
    • 我写的时候,其他答案没有发表
    • 嗯,你问你的答案有什么问题,你被告知你的答案有什么问题。您如何处理这些信息取决于您。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-18
    • 1970-01-01
    • 2023-02-20
    • 2011-06-17
    • 2022-01-24
    相关资源
    最近更新 更多