Puzzles from an arithmetic operation with Regex

Hello,

I have been so puzzled and stuck in this small code below.
I use replacer method provided by JavaScript replace() but it puzzles me why the 2nd operand becomes 2 instead of 2.1.
Any idea if I missed anything or made any mistake below?
Thank you.

let equation = "1.2+2.1"

// Regex pattern for example: 2+2 or 2.2+2.1
const addRegex = /(\d+|\d+\.\d+)(\+)(\d+|\d+\.\d+)/		

const addReplacer = (match, p1, p2, p3, offset, string) => {
  console.log(parseFloat(p1))		// 1.2
  console.log(parseFloat(p3))		// 2 <--- This is the puzzling problem. This should be 2.1 instead of 2 
  console.log(parseFloat(p1) + parseFloat(p3))	// 3.2 <--- incorrect due to incorrect 2nd operand above
  return parseFloat(p1) + parseFloat(p3)
}

while (addRegex.test(equation)) {
  console.log(equation)		// "1.2+2.1"
  equation = equation.replace(addRegex, addReplacer)
  console.log(equation)		// 3.2.1   <-- Also don't know why this changes from 3.2 to 3.2.1 here
}

The first alternative in your second group (\d) matches, so it doesn’t bother checking the second alternative.

1 Like

Thank you for reply, but if this is the reason, then why the 1st operand did not do the same thing picking up “1” but it picks up “1.2”?

Because then it wouldn’t match the string. There isn’t a “+” right after the “1”, so the first alternative doesn’t match.

1 Like

I see. By the same logic, the problem could be resolved by adding a “$” in the end of Regex:

/(\d+|\d+\.\d+)(\+)(\d+|\d+\.\d+)$/

But then this will force the search to skip if the addition operation is not in the end of equation and always only find the addition in the end of equation, which could be problematic.
Any better workaround to have this handle both integers and decimals in the same Regex pattern except setting four different Regex search patterns for four operation cases (integer + integer, integer + decimal, decimal + integer, decimal + decimal)?

And any idea why the value of

parseFloat(p1) + parseFloat(p3)

changes from 3.2 to 3.2.1?

let equation = "1.2+2.1"

// Regex pattern for example: 2+2 or 2.2+2.1
const addRegex = /(\d+|\d+\.\d+)(\+)(\d+|\d+\.\d+)/		

const addReplacer = (match, p1, p2, p3, offset, string) => {
  console.log(parseFloat(p1))		// 1.2
  console.log(parseFloat(p3))		// 2 
  console.log(parseFloat(p1) + parseFloat(p3))	// 3.2 
  return parseFloat(p1) + parseFloat(p3)
}

while (addRegex.test(equation)) {
  console.log(equation)		// "1.2+2.1"
  equation = equation.replace(addRegex, addReplacer)
  console.log(equation)		// 3.2.1   <--  why this changes from 3.2 to 3.2.1 here?
}

Seems to be same reason. If you change the regex to something like

addRegex = /(\d+\.?\d*)(\+)(\d+\.?\d*)/

Then it works.

1 Like

Thank you!
This is a much better option/solution than alternation “|”. :+1: :pray:

This * would* allow something like “1.+2.”, which you may or may not want.

I’d go with this:

(\d+(\.\d+)?)\+(\d+(\.\d+)?)
1 Like

Yes, I agree.

(\d+(\.\d+)?)\+(\d+(\.\d+)?)

This would remove the cases where dot(.) is entered but no decimals entered after dot.
This makes it more assuring.