如何对存储为字符串的实数执行数学计算?

How can I perform a mathematical calculation on real numbers stored as strings?

我有一个 class,其中包含的值有时是货币值(例如 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' 类型的操作数”。 =13=]

所以这是我的逻辑:

如果输入 "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".

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

问题是基于括号的优先顺序。由于 ToDecimal().ToString().

,它的计算结果为 Decimal - String

如果您将其更改为下面的内容,它应该可以工作

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

所以答案就在你的

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);
}

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