簡體   English   中英

確定double.Parse使用的字符數

[英]Determine the number of characters used by double.Parse

這是一個簡單的問題,但我找不到任何解決它的函數。 我需要一種方法來確定用於從字符串中解析double的字符數。

我想獲取字符串的其余部分,並通過在符號字符串表中進行簡單查找來使用它來確定它是什么測量單位。


更新

我已經給了Olivier Jacot-Descombes的答案,因為他擁有最完整的正則表達式,並且用我自己的答案打敗了我,我將如何使用正則表達式。 我看到這個答案中唯一的缺陷就是沒有考慮到不同文化的逗號和點交換位置(我在答案中考慮到了這一點,盡管它看起來有點混亂)。

但是,我將實現的實際解決方案將不使用Regex。 我仍然給出答案的原因是因為基本上我問的是錯誤的問題。 我認為正則表達式的答案是我提出的問題的最佳解決方案。

我提出的解決方案是迭代可用單位並使用inputStr.EndsWith(unitStr)與字符串進行比較,當我得到肯定匹配時,我會立即通過減去長度來知道該數字的長度來自測試字符串的單位字符串,然后我可以使用double.Parse()與左邊的內容(修剪后)。

你可以讓正則表達式返回匹配,這樣你就不需要兩次傳球。

var parseNumUnit = new Regex(
 @"(?<num>(\+|-)?([0-9,]+(\.)?[0-9]*|[0-9,]*(\.)?[0-9]+)((e|E)(\+|-)?[0-9]+)?)\s*(?<unit>[a-zA-Z]*)"
);

Match match = parseNumUnit.Match("+13.234e-3m");
string number = match.Groups["num"].Value; // "+13.234e-3" 
string unit = match.Groups["unit"].Value; // "m"

這里

(?<name>expression)    captures the expression in a group named "name".

我的數字正則表達式非常復雜,允許數字為"+13.234e-3""12.34"".25""10." "23,503.14" 如果您的數字格式更簡單,則可以簡化正則表達式。

我建議您使用RegEx,如下所示:

(?<double>[\d.]+)(?<unit>.*)

匹配時會創建兩個組,' double '和' unit '包含double值和單位。

例:

1.25632 meter

這里集團double將包含“1.25632”及本集團unit將包含“米”

我目前的解決方案是使用正則表達式來解釋浮點值,然后檢索長度以了解單位的起始位置。

    public static (double Value, string unit) Parse(string value)
    {
        var result = RegexParseDouble.Match(value);
        if(result.Success)
        {
            return (double.Parse(value.Substring(result.Length)), value.Substring(result.Length));
        }
        throw new FormatException("Value cannot be parsed as a floating point number.");
    }

    private static Regex RegexParseDouble
    {
        get => new Regex(
            @"^[-+]?(\d+" +
            Thread.CurrentThread.CurrentCulture.NumberFormat.NumberGroupSeparator +
            @"\d+)*\d*(" +
            Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator +
            @")?\d+([eE][-+]?\d+)?");
    }

理想情況下,我寧願不必自己解析字符串,然后讓.NET再次解析字符串以提供值。

一個不涉及正則表達式的簡單選項:

var input = "42,666 towels";

// Get a char[] of all numbers or separators (',' or '.', depending on language):
var numericChars = input
                    .TakeWhile(c => c == ',' || c == '.' || Char.IsNumber(c))
                    .ToArray();

// Use the chars to init a new string, which can be parsed to a number: 
var nr = Double.Parse(new String(numericChars));

// ...and the remaining part of the original string is the unit:
// (Note that we use Trim() to remove any whitespace between the number and the unit)
var unit = input.Substring(numericChars.Count()).Trim();

// Outputs: Nr is 42,666, unit is towels.
Console.WriteLine($"Nr is {nr}, unit is {unit}.");

更新

作為對下面評論的回應,繼承人是一個擴張。 我承認這會破壞上面的優雅簡約,但至少它是可讀的,可配置的(可擴展的),它的工作原理如下:

var nrFormat = System.Globalization.CultureInfo.CurrentCulture.NumberFormat;

// Remove or add strings to this list as needed:
var validStrings = 
    new List<string>{ 
                    nrFormat.NaNSymbol, 
                    nrFormat.NegativeSign, 
                    nrFormat.NumberDecimalSeparator, 
                    nrFormat.PercentGroupSeparator, 
                    nrFormat.PercentSymbol, 
                    nrFormat.PerMilleSymbol, 
                    nrFormat.PositiveInfinitySymbol, 
                    nrFormat.PositiveSign
                };

validStrings.AddRange(nrFormat.NativeDigits);
validStrings.Add("^");
validStrings.Add("e");
validStrings.Add("E");
validStrings.Add(" ");


// You can use more complex numbers, like: 
var input = "-42,666e-3 Towels";

// Get all numbers or separators (',' or '.', depending on language):
var numericChars = input.TakeWhile(c => validStrings.Contains("" + c)).ToArray();

// Use the chars to init a new string, which can be parsed to a number: 
var nr = Double.Parse(new String(numericChars));

// ...and the remaining part of the original string is the unit:
// (Note that we use Trim() to remove any whitespace between the number and the unit)
var unit = input.Substring(numericChars.Count()).Trim();

// Outputs is now: "Nr is -0,042666, unit is Towels"
Console.WriteLine($"Nr is {nr}, unit is {unit}.");

如您所見,輸入現在可能要復雜得多; 你甚至可以使用像var input = "∞ Garden Gnomes"; ,這將產生精彩的輸出:

Nr是∞,單位是Garden Gnomes。

這是我發現的非正則表達式解決方案。 如果您可以保證您的輸入始終采用格式number-space-unit,那么您可以簡單地執行以下操作:

public static (double Value, string unit) Parse(string value)
{
    var values = value.Split(" ");

    double number;
    if (!double.TryParse(values[0], out number))
        throw new FormatException("Value cannot be parsed as a floating point number.");

    string unit = values[1];

    return (number, unit);
}

如果您的輸入字符串格式是其他但是一致的,您可以執行與此類似的操作以匹配該格式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM