public virtual ParseResult Parse(ExtractResult extResult) { // Check if the parser is configured to support specific types if (SupportedTypes != null && !SupportedTypes.Any(t => extResult.Type.Equals(t, StringComparison.Ordinal))) { return(null); } ParseResult ret = null; if (!(extResult.Data is string extra)) { extra = LongFormatRegex.Match(extResult.Text).Success ? Constants.NUMBER_SUFFIX : Config.LanguageMarker; } // Resolve symbol prefix var isNegative = false; var matchNegative = Config.NegativeNumberSignRegex.Match(extResult.Text); if (matchNegative.Success) { isNegative = true; extResult.Text = extResult.Text.Substring(matchNegative.Groups["negTerm"].Length); } // Assign resolution value if (extResult.Data is List <ExtractResult> ers) { var innerPrs = ers.Select(Parse).ToList(); var mergedPrs = new List <ParseResult>(); double val = 0; var count = 0; for (var idx = 0; idx < innerPrs.Count; idx++) { val += (double)innerPrs[idx].Value; if (idx + 1 >= innerPrs.Count || !IsMergeable((double)innerPrs[idx].Value, (double)innerPrs[idx + 1].Value)) { var start = (int)ers[idx - count].Start; var length = (int)(ers[idx].Start + ers[idx].Length - start); mergedPrs.Add(new ParseResult { Start = start, Length = length, Text = extResult.Text.Substring((int)(start - extResult.Start), length), Type = extResult.Type, Value = val, Data = null, }); val = 0; count = 0; } else { count++; } } ret = new ParseResult(extResult) { Value = val, Data = mergedPrs }; } else if (extra.Contains(Constants.NUMBER_SUFFIX)) { ret = DigitNumberParse(extResult); } else if (extra.Contains($"{Constants.FRACTION_PREFIX}{Config.LanguageMarker}")) { // Such fractions are special cases, parse via another method ret = FracLikeNumberParse(extResult); } else if (extra.Contains(Config.LanguageMarker)) { ret = TextNumberParse(extResult); } else if (extra.Contains(Constants.POWER_SUFFIX)) { ret = PowerNumberParse(extResult); } if (ret?.Data is List <ParseResult> prs) { foreach (var parseResult in prs) { parseResult.ResolutionStr = GetResolutionStr(parseResult.Value); } } else if (ret?.Value != null) { if (isNegative) { // Recover the original extracted Text ret.Text = matchNegative.Groups["negTerm"].Value + extResult.Text; ret.Value = -(double)ret.Value; } ret.ResolutionStr = GetResolutionStr(ret.Value); } // Add "offset" and "relativeTo" for ordinal if (!string.IsNullOrEmpty(ret.Type) && ret.Type.Contains(Constants.MODEL_ORDINAL)) { if ((this.Config.Config.Options & NumberOptions.SuppressExtendedTypes) == 0 && ret.Metadata.IsOrdinalRelative) { var offset = Config.RelativeReferenceOffsetMap[extResult.Text]; var relativeTo = Config.RelativeReferenceRelativeToMap[extResult.Text]; ret.Metadata.Offset = offset; ret.Metadata.RelativeTo = relativeTo; // Add value for ordinal.relative string sign = offset[0].Equals('-') ? string.Empty : "+"; ret.Value = string.Concat(relativeTo, sign, offset); ret.ResolutionStr = GetResolutionStr(ret.Value); } else { ret.Metadata.Offset = ret.ResolutionStr; // Every ordinal number is relative to the start ret.Metadata.RelativeTo = Constants.RELATIVE_START; } } if (ret != null) { ret.Type = DetermineType(extResult); ret.Text = ret.Text.ToLowerInvariant(); } return(ret); }
public virtual List <ExtractResult> Extract(string source) { if (string.IsNullOrEmpty(source)) { return(new List <ExtractResult>()); } var results = new List <ExtractResult>(); var matchSource = new Dictionary <Tuple <int, int>, string>(); var matched = new bool[source.Length]; var collections = Regexes.ToDictionary(o => o.Key.Matches(source), p => p.Value); foreach (var collection in collections) { foreach (Match m in collection.Key) { GetMatchedStartAndLength(m, collection.Value, source, out int start, out int length); if (start >= 0 && length > 0) { for (var j = 0; j < length; j++) { matched[start + j] = true; } // Keep Source Data for extra information matchSource.Add(new Tuple <int, int>(start, length), collection.Value); } } } var last = -1; for (var i = 0; i < source.Length; i++) { if (matched[i]) { if (i + 1 == source.Length || !matched[i + 1]) { var start = last + 1; var length = i - last; var substr = source.Substring(start, length); if (matchSource.Keys.Any(o => o.Item1 == start && o.Item2 == length)) { var srcMatch = matchSource.Keys.First(o => o.Item1 == start && o.Item2 == length); var er = new ExtractResult { Start = start, Length = length, Text = substr, Type = ExtractType, Data = matchSource.ContainsKey(srcMatch) ? matchSource[srcMatch] : null, }; results.Add(er); } } } else { last = i; } } // In ExperimentalMode, cases like "from 3 to 5" and "between 10 and 15" are set to closed at both start and end if ((Options & NumberOptions.ExperimentalMode) != 0) { foreach (var result in results) { if (result.Data.ToString() == NumberRangeConstants.TWONUMBETWEEN || result.Data.ToString() == NumberRangeConstants.TWONUMTILL) { result.Data = NumberRangeConstants.TWONUMCLOSED; } } } return(results); }
public virtual ParseResult TextNumberParse(ExtractResult extResult) { var result = new ParseResult { Start = extResult.Start, Length = extResult.Length, Text = extResult.Text, Type = extResult.Type, Metadata = extResult.Metadata, }; var handle = extResult.Text; handle = Config.HalfADozenRegex.Replace(handle, Config.HalfADozenText); // Handling cases like "last", "next one", "previous one" if ((this.Config.Config.Options & NumberOptions.SuppressExtendedTypes) == 0) { if (extResult.Metadata != null && extResult.Metadata.IsOrdinalRelative) { return(result); } } var numGroup = handle.Split(Config.WrittenDecimalSeparatorTexts.ToArray(), StringSplitOptions.RemoveEmptyEntries); var intPart = numGroup[0]; var stringMatch = TextNumberRegex.Match(intPart); // Store all match str. var matchStrs = new List <string>(); while (stringMatch.Success) { var matchStr = stringMatch.Groups[0].Value; matchStrs.Add(matchStr); stringMatch = stringMatch.NextMatch(); } // Get the value recursively var intPartRet = GetIntValue(matchStrs); double pointPartRet = 0; if (numGroup.Length == 2) { var pointPart = numGroup[1]; stringMatch = TextNumberRegex.Match(pointPart); matchStrs.Clear(); while (stringMatch.Success) { var matchStr = stringMatch.Groups[0].Value; matchStrs.Add(matchStr); stringMatch = stringMatch.NextMatch(); } pointPartRet += GetPointValue(matchStrs); } result.Value = intPartRet + pointPartRet; return(result); }
public virtual ParseResult FracLikeNumberParse(ExtractResult extResult) { var result = new ParseResult { Start = extResult.Start, Length = extResult.Length, Text = extResult.Text, Type = extResult.Type, }; var resultText = extResult.Text; if (Config.FractionPrepositionRegex.IsMatch(resultText)) { var match = Config.FractionPrepositionRegex.Match(resultText); var numerator = match.Groups["numerator"].Value; var denominator = match.Groups["denominator"].Value; var smallValue = char.IsDigit(numerator[0]) ? GetDigitalValue(numerator, 1) : GetIntValue(Utilities.RegExpUtility.GetMatches(this.TextNumberRegex, numerator)); var bigValue = char.IsDigit(denominator[0]) ? GetDigitalValue(denominator, 1) : GetIntValue(Utilities.RegExpUtility.GetMatches(this.TextNumberRegex, denominator)); result.Value = smallValue / bigValue; } else { var fracWords = Config.NormalizeTokenSet(resultText.Split(null), result).ToList(); // Split fraction with integer var splitIndex = fracWords.Count - 1; var currentValue = Config.ResolveCompositeNumber(fracWords[splitIndex]); long roundValue = 1; // For case like "half" if (fracWords.Count == 1) { result.Value = 1 / GetIntValue(fracWords); return(result); } for (splitIndex = fracWords.Count - 2; splitIndex >= 0; splitIndex--) { if (Config.WrittenFractionSeparatorTexts.Contains(fracWords[splitIndex]) || Config.WrittenIntegerSeparatorTexts.Contains(fracWords[splitIndex])) { continue; } var previousValue = currentValue; currentValue = Config.ResolveCompositeNumber(fracWords[splitIndex]); var hundredsSM = 100; // Previous : hundred // Current : one if ((previousValue >= hundredsSM && previousValue > currentValue) || (previousValue < hundredsSM && IsComposable(currentValue, previousValue))) { if (previousValue < hundredsSM && currentValue >= roundValue) { roundValue = currentValue; } else if (previousValue < hundredsSM && currentValue < roundValue) { splitIndex++; break; } // Current is the first word if (splitIndex == 0) { // Scan, skip the first word splitIndex = 1; while (splitIndex <= fracWords.Count - 2) { // e.g. one hundred thousand // frac[i+1] % 100 && frac[i] % 100 = 0 if (Config.ResolveCompositeNumber(fracWords[splitIndex]) >= hundredsSM && !Config.WrittenFractionSeparatorTexts.Contains(fracWords[splitIndex + 1]) && Config.ResolveCompositeNumber(fracWords[splitIndex + 1]) < hundredsSM) { splitIndex++; break; } splitIndex++; } break; } continue; } splitIndex++; break; } if (splitIndex < 0) { splitIndex = 0; } var fracPart = new List <string>(); for (var i = splitIndex; i < fracWords.Count; i++) { if (fracWords[i].Contains("-")) { var split = fracWords[i].Split('-'); fracPart.Add(split[0]); fracPart.Add("-"); fracPart.Add(split[1]); } else { fracPart.Add(fracWords[i]); } } fracWords.RemoveRange(splitIndex, fracWords.Count - splitIndex); // Split mixed number with fraction var denominator = GetIntValue(fracPart); double numerValue = 0; double intValue = 0; var mixedIndex = fracWords.Count; for (var i = fracWords.Count - 1; i >= 0; i--) { if (i < fracWords.Count - 1 && Config.WrittenFractionSeparatorTexts.Contains(fracWords[i])) { var numerStr = string.Join(" ", fracWords.GetRange(i + 1, fracWords.Count - 1 - i)); numerValue = GetIntValue(Utilities.RegExpUtility.GetMatches(this.TextNumberRegex, numerStr)); mixedIndex = i + 1; break; } } var intStr = string.Join(" ", fracWords.GetRange(0, mixedIndex)); intValue = GetIntValue(Utilities.RegExpUtility.GetMatches(this.TextNumberRegex, intStr)); // Find mixed number if (mixedIndex != fracWords.Count && numerValue < denominator) { result.Value = intValue + (numerValue / denominator); } else { result.Value = (intValue + numerValue) / denominator; } } return(result); }
protected ParseResult FracLikeNumberParse(ExtractResult extResult) { var result = new ParseResult { Start = extResult.Start, Length = extResult.Length, Text = extResult.Text, Type = extResult.Type }; var resultText = extResult.Text.ToLower(); if (resultText.Contains($@"{config.FractionMarkerToken}")) { var overIndex = resultText.IndexOf(config.FractionMarkerToken, StringComparison.Ordinal); var smallPart = resultText.Substring(0, overIndex).Trim(); var bigPart = resultText.Substring(overIndex + config.FractionMarkerToken.Length, resultText.Length - overIndex - config.FractionMarkerToken.Length).Trim(); var smallValue = char.IsDigit(smallPart[0]) ? GetDigitalValue(smallPart, 1) : GetIntValue(GetMatches(smallPart)); var bigValue = char.IsDigit(bigPart[0]) ? GetDigitalValue(bigPart, 1) : GetIntValue(GetMatches(bigPart)); result.Value = smallValue / bigValue; } else { var fracWords = config.NormalizeTokenSet(resultText.Split(null), result).ToList(); // Split fraction with integer var splitIndex = fracWords.Count - 1; var currentValue = config.ResolveCompositeNumber(fracWords[splitIndex]); long roundValue = 1; for (splitIndex = fracWords.Count - 2; splitIndex >= 0; splitIndex--) { if (config.WrittenFractionSeparatorTexts.Contains(fracWords[splitIndex])) { continue; } var previousValue = currentValue; currentValue = config.ResolveCompositeNumber(fracWords[splitIndex]); // previous : hundred // current : one if ((previousValue >= 100 && previousValue > currentValue) || (previousValue < 100 && IsComposable(currentValue, previousValue))) { if (previousValue < 100 && currentValue >= roundValue) { roundValue = currentValue; } else if (previousValue < 100 && currentValue < roundValue) { splitIndex++; break; } // current is the first word if (splitIndex == 0) { // scan, skip the first word splitIndex = 1; while (splitIndex <= fracWords.Count - 2) { // e.g. one hundred thousand // frac[i+1] % 100 && frac[i] % 100 = 0 if (config.ResolveCompositeNumber(fracWords[splitIndex]) >= 100 && !config.WrittenFractionSeparatorTexts.Contains(fracWords[splitIndex + 1]) && config.ResolveCompositeNumber(fracWords[splitIndex + 1]) < 100) { splitIndex++; break; } splitIndex++; } break; } continue; } splitIndex++; break; } var fracPart = new List <string>(); for (var i = splitIndex; i < fracWords.Count; i++) { if (fracWords[i].Contains("-")) { var split = fracWords[i].Split('-'); fracPart.Add(split[0]); fracPart.Add("-"); fracPart.Add(split[1]); } else { fracPart.Add(fracWords[i]); } } fracWords.RemoveRange(splitIndex, fracWords.Count - splitIndex); // denomi = denominator var denomiValue = GetIntValue(fracPart); // Split mixed number with fraction double numerValue = 0; double intValue = 0; var mixedIndex = fracWords.Count; for (var i = fracWords.Count - 1; i >= 0; i--) { if (i < fracWords.Count - 1 && config.WrittenFractionSeparatorTexts.Contains(fracWords[i])) { var numerStr = string.Join(" ", fracWords.GetRange(i + 1, fracWords.Count - 1 - i)); numerValue = GetIntValue(GetMatches(numerStr)); mixedIndex = i + 1; break; } } var intStr = string.Join(" ", fracWords.GetRange(0, mixedIndex)); intValue = GetIntValue(GetMatches(intStr)); // Find mixed number if (mixedIndex != fracWords.Count && numerValue < denomiValue) { result.Value = intValue + numerValue / denomiValue; } else { result.Value = (intValue + numerValue) / denomiValue; } } return(result); }
public virtual ParseResult PowerNumberParse(ExtractResult extResult) { var result = new ParseResult { Start = extResult.Start, Length = extResult.Length, Text = extResult.Text, Type = extResult.Type, }; var handle = extResult.Text.ToUpperInvariant(); var isE = !extResult.Text.Contains("^"); // [1] 1e10 // [2] 1.1^-23 var calStack = new Queue <double>(); double scale = 10; var dot = false; var isNegative = false; double tmp = 0; for (var i = 0; i < handle.Length; i++) { var ch = handle[i]; if (ch == '^' || ch == 'E') { if (isNegative) { calStack.Enqueue(-tmp); } else { calStack.Enqueue(tmp); } tmp = 0; scale = 10; dot = false; isNegative = false; } else if (ch >= '0' && ch <= '9') { if (dot) { tmp = tmp + (scale * (ch - '0')); scale *= 0.1; } else { tmp = (tmp * scale) + (ch - '0'); } } else if (ch == Config.DecimalSeparatorChar) { dot = true; scale = 0.1; } else if (ch == '-') { isNegative = !isNegative; } else if (ch == '+') { continue; } if (i == handle.Length - 1) { if (isNegative) { calStack.Enqueue(-tmp); } else { calStack.Enqueue(tmp); } } } double ret; if (isE) { ret = calStack.Dequeue() * Math.Pow(10, calStack.Dequeue()); } else { ret = Math.Pow(calStack.Dequeue(), calStack.Dequeue()); } result.Value = ret; result.ResolutionStr = ret.ToString(CultureInfo.InvariantCulture); return(result); }
protected ParseResult TextNumberParse(ExtractResult extResult) { var result = new ParseResult { Start = extResult.Start, Length = extResult.Length, Text = extResult.Text, Type = extResult.Type }; var handle = extResult.Text.ToLower(); #region dozen special handle = config.HalfADozenRegex.Replace(handle, config.HalfADozenText); #endregion var numGroup = handle.Split(config.WrittenDecimalSeparatorTexts.ToArray(), StringSplitOptions.RemoveEmptyEntries); #region intPart var intPart = numGroup[0]; var sMatch = TextNumberRegex.Match(intPart); var matchStrs = new List <string>(); //Store all match str. while (sMatch.Success) { var matchStr = sMatch.Groups[0].Value.ToLower(); matchStrs.Add(matchStr); sMatch = sMatch.NextMatch(); } //Get the value recursively var intPartRet = GetIntValue(matchStrs); #endregion #region PointPart double pointPartRet = 0; if (numGroup.Length == 2) { var pointPart = numGroup[1]; sMatch = TextNumberRegex.Match(pointPart); matchStrs.Clear(); while (sMatch.Success) { var matchStr = sMatch.Groups[0].Value.ToLower(); matchStrs.Add(matchStr); sMatch = sMatch.NextMatch(); } pointPartRet += GetPointValue(matchStrs); } #endregion result.Value = intPartRet + pointPartRet; return(result); }
public virtual List <ExtractResult> Extract(string source) { if (string.IsNullOrEmpty(source)) { return(new List <ExtractResult>()); } var result = new List <ExtractResult>(); var matchSource = new Dictionary <Tuple <int, int>, string>(); var matched = new bool[source.Length]; var collections = Regexes.ToDictionary(o => o.Key.Matches(source), p => p.Value); foreach (var collection in collections) { foreach (Match m in collection.Key) { GetMatchedStartAndLength(m, collection.Value, source, out int start, out int length); if (start >= 0 && length > 0) { for (var j = 0; j < length; j++) { matched[start + j] = true; } // Keep Source Data for extra information matchSource.Add(new Tuple <int, int>(start, length), collection.Value); } } } var last = -1; for (var i = 0; i < source.Length; i++) { if (matched[i]) { if (i + 1 == source.Length || !matched[i + 1]) { var start = last + 1; var length = i - last; var substr = source.Substring(start, length); if (matchSource.Keys.Any(o => o.Item1 == start && o.Item2 == length)) { var srcMatch = matchSource.Keys.First(o => o.Item1 == start && o.Item2 == length); var er = new ExtractResult { Start = start, Length = length, Text = substr, Type = ExtractType, Data = matchSource.ContainsKey(srcMatch) ? matchSource[srcMatch] : null }; result.Add(er); } } } else { last = i; } } return(result); }
public virtual List <ExtractResult> Extract(string source) { if (string.IsNullOrEmpty(source)) { return(new List <ExtractResult>()); } var results = new List <ExtractResult>(); var matchSource = new Dictionary <Tuple <int, int>, string>(); var matched = new bool[source.Length]; var collections = Regexes.ToDictionary(o => o.Key.Matches(source), p => p.Value); foreach (var collection in collections) { foreach (Match m in collection.Key) { GetMatchedStartAndLength(m, collection.Value, source, out int start, out int length); if (start >= 0 && length > 0) { // Keep Source Data for extra information matchSource.Add(new Tuple <int, int>(start, length), collection.Value); } } } foreach (var match in matchSource) { var start = match.Key.Item1; var length = match.Key.Item2; // Filter wrong two number ranges such as "more than 20 and less than 10" and "大于20小于10". if (match.Value.Equals(NumberRangeConstants.TWONUM)) { int moreIndex = 0, lessIndex = 0; var text = source.Substring(match.Key.Item1, match.Key.Item2); var er = numberExtractor.Extract(text); if (er.Count != 2) { er = ordinalExtractor.Extract(text); if (er.Count != 2) { continue; } } var nums = er.Select(r => (double)(numberParser.Parse(r).Value ?? 0)).ToList(); moreIndex = matchSource.First(r => r.Value.Equals(NumberRangeConstants.MORE) && r.Key.Item1 >= start && r.Key.Item1 + r.Key.Item2 <= start + length).Key.Item1; lessIndex = matchSource.First(r => r.Value.Equals(NumberRangeConstants.LESS) && r.Key.Item1 >= start && r.Key.Item1 + r.Key.Item2 <= start + length).Key.Item1; if (!((nums[0] < nums[1] && moreIndex <= lessIndex) || (nums[0] > nums[1] && moreIndex >= lessIndex))) { continue; } } // The entity is longer than 1, so don't mark the last char to represent the end. // To avoid no connector cases like "大于20小于10" being marked as a whole entity. for (var j = 0; j < length - 1; j++) { matched[start + j] = true; } } var last = -1; for (var i = 0; i < source.Length; i++) { if (matched[i]) { if (i + 1 == source.Length || !matched[i + 1]) { var start = last + 1; var length = i - last + 1; var substr = source.Substring(start, length); if (matchSource.Keys.Any(o => o.Item1 == start && o.Item2 == length)) { var srcMatch = matchSource.Keys.First(o => o.Item1 == start && o.Item2 == length); var er = new ExtractResult { Start = start, Length = length, Text = substr, Type = ExtractType, Data = matchSource.ContainsKey(srcMatch) ? matchSource[srcMatch] : null, }; results.Add(er); } } } else { last = i; } } // In ExperimentalMode, cases like "from 3 to 5" and "between 10 and 15" are set to closed at both start and end if ((Config.Options & NumberOptions.ExperimentalMode) != 0) { foreach (var result in results) { var data = result.Data.ToString(); if (data == NumberRangeConstants.TWONUMBETWEEN || data == NumberRangeConstants.TWONUMTILL) { result.Data = NumberRangeConstants.TWONUMCLOSED; } } } return(results); }
public override ParseResult Parse(ExtractResult extResult) { // check if the parser is configured to support specific types if (SupportedTypes != null && !SupportedTypes.Any(t => extResult.Type.Equals(t))) { return(null); } string extra = null; ParseResult ret = null; extra = extResult.Data as string; var getExtResult = new ExtractResult() { Start = extResult.Start, Length = extResult.Length, Data = extResult.Data, Text = extResult.Text, Type = extResult.Type }; if (Config.CultureInfo.Name == "zh-CN") { getExtResult.Text = ReplaceTraWithSim(getExtResult.Text); } if (extra == null) { return(null); } if (extra.Contains("Integer")) { ret = ParseInteger(getExtResult); } else if (extra.Contains("Per")) { ret = ParsePercentage(getExtResult); } else if (extra.Contains("Num")) { getExtResult.Text = NormalizeCharWidth(getExtResult.Text); ret = DigitNumberParse(getExtResult); if (Config.NegativeNumberSignRegex.IsMatch(getExtResult.Text) && (double)ret.Value > 0) { ret.Value = -(double)ret.Value; } ret.ResolutionStr = ret.Value.ToString(); } else if (extra.Contains("Pow")) { getExtResult.Text = NormalizeCharWidth(getExtResult.Text); ret = PowerNumberParse(getExtResult); ret.ResolutionStr = ret.Value.ToString(); } else if (extra.Contains("Frac")) { ret = ParseFraction(getExtResult); } else if (extra.Contains("Dou")) { ret = ParseDouble(getExtResult); } else if (extra.Contains("Ordinal")) { ret = ParseOrdinal(getExtResult); } if (ret != null) { ret.Text = extResult.Text; } return(ret); }
// Parse percentage phrase. protected ParseResult ParsePercentage(ExtractResult extResult) { var result = new ParseResult { Start = extResult.Start, Length = extResult.Length, Text = extResult.Text, Type = extResult.Type }; var resultText = extResult.Text; long power = 1; if (extResult.Data.ToString().Contains("Spe")) { resultText = NormalizeCharWidth(resultText); resultText = ReplaceUnit(resultText); if (resultText == "半額" || resultText == "半値" || resultText == "半折") { result.Value = 50; } else if (resultText == "10成" || resultText == "10割" || resultText == "十割") { result.Value = 100; } else { var matches = Config.SpeGetNumberRegex.Matches(resultText); double intNumber; if (matches.Count == 2) { var intNumberChar = matches[0].Value[0]; if (intNumberChar == '対' || intNumberChar == '对') { intNumber = 5; } else if (intNumberChar == '十' || intNumberChar == '拾') { intNumber = 10; } else { intNumber = Config.ZeroToNineMap[intNumberChar]; } var pointNumberChar = matches[1].Value[0]; double pointNumber; if (pointNumberChar == '半') { pointNumber = 0.5; } else { pointNumber = Config.ZeroToNineMap[pointNumberChar] * 0.1; } result.Value = (intNumber + pointNumber) * 10; } else if (matches.Count == 5) { // Deal the Japanese percentage case like "xxx割xxx分xxx厘", get the integer value and convert into result. var intNumberChar = matches[0].Value[0]; var pointNumberChar = matches[1].Value[0]; var dotNumberChar = matches[3].Value[0]; double pointNumber = Config.ZeroToNineMap[pointNumberChar] * 0.1; double dotNumber = Config.ZeroToNineMap[dotNumberChar] * 0.01; intNumber = Config.ZeroToNineMap[intNumberChar]; result.Value = (intNumber + pointNumber + dotNumber) * 10; } else { var intNumberChar = matches[0].Value[0]; if (intNumberChar == '対' || intNumberChar == '对') { intNumber = 5; } else if (intNumberChar == '十' || intNumberChar == '拾') { intNumber = 10; } else { intNumber = Config.ZeroToNineMap[intNumberChar]; } result.Value = intNumber * 10; } } } else if (extResult.Data.ToString().Contains("Num")) { var doubleText = Config.PercentageRegex.Match(resultText).Value; if (doubleText.Contains("k") || doubleText.Contains("K") || doubleText.Contains("k") || doubleText.Contains("K")) { power = 1000; } if (doubleText.Contains("M") || doubleText.Contains("M")) { power = 1000000; } if (doubleText.Contains("G") || doubleText.Contains("G")) { power = 1000000000; } if (doubleText.Contains("T") || doubleText.Contains("T")) { power = 1000000000000; } result.Value = GetDigitValue(resultText, power); } else { var doubleText = Config.PercentageRegex.Match(resultText).Value; doubleText = ReplaceUnit(doubleText); var splitResult = Config.PointRegex.Split(doubleText); if (splitResult[0] == "") { splitResult[0] = "零"; } var doubleValue = GetIntValue(splitResult[0]); if (splitResult.Length == 2) { if (Config.NegativeNumberSignRegex.IsMatch(splitResult[0])) { doubleValue -= GetPointValue(splitResult[1]); } else { doubleValue += GetPointValue(splitResult[1]); } } result.Value = doubleValue; } result.ResolutionStr = result.Value + @"%"; return(result); }