in libraries/bot-dialogs/src/main/java/com/microsoft/recognizers/text/number/parsers/BaseNumberParser.java [169:296]
private ParseResult fracLikeNumberParse(ExtractResult extractResult) {
ParseResult result = new ParseResult(extractResult.getStart(), extractResult.getLength(), extractResult.getText(), extractResult.getType(), null, null, null);
String resultText = extractResult.getText().toLowerCase();
Matcher match = config.getFractionPrepositionRegex().matcher(resultText);
if (match.find()) {
String numerator = match.group("numerator");
String denominator = match.group("denominator");
double smallValue = Character.isDigit(numerator.charAt(0)) ?
getDigitalValue(numerator, 1) :
getIntValue(getMatches(numerator));
double bigValue = Character.isDigit(denominator.charAt(0)) ?
getDigitalValue(denominator, 1) :
getIntValue(getMatches(denominator));
result.setValue(smallValue / bigValue);
} else {
List<String> fracWords = config.normalizeTokenSet(Arrays.asList(resultText.split(" ")), result);
// Split fraction with integer
int splitIndex = fracWords.size() - 1;
long currentValue = config.resolveCompositeNumber(fracWords.get(splitIndex));
long roundValue = 1;
// For case like "half"
if (fracWords.size() == 1) {
result.setValue(1 / getIntValue(fracWords));
return result;
}
for (splitIndex = fracWords.size() - 2; splitIndex >= 0; splitIndex--) {
String fracWord = fracWords.get(splitIndex);
if (config.getWrittenFractionSeparatorTexts().contains(fracWord) ||
config.getWrittenIntegerSeparatorTexts().contains(fracWord)) {
continue;
}
long previousValue = currentValue;
currentValue = config.resolveCompositeNumber(fracWord);
int smHundreds = 100;
// previous : hundred
// current : one
if ((previousValue >= smHundreds && previousValue > currentValue) ||
(previousValue < smHundreds && isComposable(currentValue, previousValue))) {
if (previousValue < smHundreds && currentValue >= roundValue) {
roundValue = currentValue;
} else if (previousValue < smHundreds && currentValue < roundValue) {
splitIndex++;
break;
}
// current is the first word
if (splitIndex == 0) {
// scan, skip the first word
splitIndex = 1;
while (splitIndex <= fracWords.size() - 2) {
// e.g. one hundred thousand
// frac[i+1] % 100 && frac[i] % 100 = 0
if (config.resolveCompositeNumber(fracWords.get(splitIndex)) >= smHundreds &&
!config.getWrittenFractionSeparatorTexts().contains(fracWords.get(splitIndex + 1)) &&
config.resolveCompositeNumber(fracWords.get(splitIndex + 1)) < smHundreds) {
splitIndex++;
break;
}
splitIndex++;
}
break;
}
continue;
}
splitIndex++;
break;
}
if (splitIndex < 0) {
splitIndex = 0;
}
List<String> fracPart = new ArrayList<String>();
for (int i = splitIndex; i < fracWords.size(); i++) {
if (fracWords.get(i).contains("-")) {
String[] split = fracWords.get(i).split(Pattern.quote("-"));
fracPart.add(split[0]);
fracPart.add("-");
fracPart.add(split[1]);
} else {
fracPart.add(fracWords.get(i));
}
}
fracWords.subList(splitIndex, fracWords.size()).clear();
// denomi = denominator
double denomiValue = getIntValue(fracPart);
// Split mixed number with fraction
double numerValue = 0;
double intValue = 0;
int mixedIndex = fracWords.size();
for (int i = fracWords.size() - 1; i >= 0; i--) {
if (i < fracWords.size() - 1 && config.getWrittenFractionSeparatorTexts().contains(fracWords.get(i))) {
String numerStr = String.join(" ", fracWords.subList(i + 1, fracWords.size()));
numerValue = getIntValue(getMatches(numerStr));
mixedIndex = i + 1;
break;
}
}
String intStr = String.join(" ", fracWords.subList(0, mixedIndex));
intValue = getIntValue(getMatches(intStr));
// Find mixed number
if (mixedIndex != fracWords.size() && numerValue < denomiValue) {
result.setValue(intValue + numerValue / denomiValue);
} else {
result.setValue((intValue + numerValue) / denomiValue);
}
}
return result;
}