How to scan complex numbers in java - java

How can i scan number inserted in this form: 1.7+2.8990i in java? I imagine its possible to split the line one time with +, or -? How should i take this line as a string or sth else?
Thanks

If you wanted to use a library there is always Commons Math which lets you do stuff like this:
ComplexFormat cf = new ComplexFormat();
Complex c = cf.parse("1.110 + 2.222i");
Complex second = new Complex(2.0, 5.0);
Complex answer = c.log(); // natural logarithm.
answer = c.cos(); // cosine
answer = c.pow(second); // first raised to the power of second
ComplexFormat format = new ComplexFormat(); // default format
String s1 = format.format(c); // s1 contains "1.110 + 2.222i"
String s2 = format.format(second); // s2 contains "2.0 + 5.0i"

Here is a RegEx approach (without external library but also without ability to use a Complex Number for more than just parsing):
Pattern pattern = Pattern.compile("([+-]?\\d*\\.\\d+)([+-]?\\d*\\.\\d+)i",Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
Matcher matcher = pattern.matcher("1.7+2.8990i");
if(matcher.matches()) {
System.out.println("a:" + Float.parseFloat(matcher.group(1)));
System.out.println("b:" + Float.parseFloat(matcher.group(2)));
} else {
System.out.println("Not a complex number");
}
This approach supports positive and negative values for a and b. Now one weaknesses to this approach are it doesn't tolerate spaces around number (you could safely strip spaces from your input and not alter the equation).

Related

Java regex pattern overmatching(Pattern matches one sequence instead of two)

When I write: "integralfrom1to10ofx^2)+integralfrom1to10ofx^3)",
I expect my regex:
// INTEGRAL BASIC
Pattern integralFinalPattern = Pattern.compile("integralfrom(.*)to(.*)of(.*)\\)");
Matcher integralFinalMatcher = integralFinalPattern.matcher(regexDedicatedString);
if(integralFinalMatcher.find()){
String integral_user_input = integralFinalMatcher.group(0);
String integral_lower_index = integralFinalMatcher.group(1);
String integral_upper_index = integralFinalMatcher.group(2);
String integral_formula = integralFinalMatcher.group(3);
String ultimateLatexIntegral = "(\\int_{"+ integral_lower_index
+"}^{"+ integral_upper_index +"} " + integral_formula + ")";
mathFormula = mathFormula.replace(integral_user_input, ultimateLatexIntegral);
}
to match these two strings separately, but for now it would interpret it as one.
And in result of it I'd get the following latex SVG:
I would like to have output with two separate integrals, like here:
How can I achieve this with regex?
Obviously, I seek for an idea that would make it work for more than two pieces.
You're doing a lot of work that the Matcher class can do for you. Check it out:
Pattern p = Pattern.compile("integralfrom(?<upper>.*?)to(?<lower>.*?)of(?<formula>.*?)\\)");
Matcher m = p.matcher(subject);
result = m.replaceAll("\\\\int_{${upper}}^{${lower}} (${formula})");
With an input of "integralfrom1to10ofx^2)+integralfrom1to10ofx^3)", the result is:
\int_{1}^{10} (x^2)+\int_{1}^{10} (x^3)

JAVA How do i apply digit grouping to a equation

I am trying to digit group an equation inputted by the user with indeterminate in size for example; 9000 + 1000 x 2 this is stored in a string and I want to turn it into 9,000 + 1,000 x 2. The code I have at the moment will only work until it reaches a non-number is there I way I can record the location of where it found the non-number and skip over it to get to the next number.
My code so far;
DecimalFormat formatter = new DecimalFormat("#,###.##");
if(loop == true) {
double amount = ((Number)NumberFormat.getInstance().parse(CalculatorComponent.values)).intValue();
temp = formatter.format(amount);
System.out.println(temp);
}
the loop variable is always set to true at present, and CalculatorComponent.values is a string of the currently inputted data, this includes the operators.
Here's a solution parsing your input with regular expressions and replacing the values.
// your format
DecimalFormat formatter = new DecimalFormat("#,###.##");
// your input
String input = "9000 + 1000 x 2";
// StringBuffer holding the replaced String
StringBuffer result = new StringBuffer(input.length());
// pattern for 1+ consecutive digits
Pattern pattern = Pattern.compile("\\d+");
// matcher for your input
Matcher matcher = pattern.matcher(input);
// iterating over matches
while (matcher.find()) {
// replacing matches
matcher.appendReplacement(
result,
formatter.format(Integer.valueOf(matcher.group()))
);
}
// appending tail (not applicable in this example, but need to have)
matcher.appendTail(result);
// printing result
System.out.println(result);
Output
9,000 + 1,000 x 2
Notes
Matcher#appendReplacement takes a StringBuffer, not a StringBuilder - never figured out why, afaik it doesn't leverage any multi-threaded operations
You need to convert the digit matches to Number in order to format them (hence the Integer.valueOf invocation), but that operation is safe in this context
The Matcher#appendTail invocation is useful if you have any non-matching text after the last token, so it can be added to the result too
This will work for plain digit integer numbers. However, if you have already localized number expressions in your equation, or decimal numbers , you're probably going to need a fine-tuned pattern

using java to find and replace without markup

I'm fairly certain this is asked & answered, but I cant find an (that) answer, so I'll ask:
I want to use javas regex to find and replace. There is no markup involved (no, "${ImMarkup!} in the source string) and the value I wish to replace is contextualized (as in, I cant write a simple replace A with B).
Examples make everything easier, here's some sample code. This is the source string:
! locator's position P1(p1x,p1y),P2(p2x,p2y)
R,1,0.001,0.001,0.001,0.001, , ,
RMORE, , , ,
RMORE
RMORE, ,
ET,MPTEMP,,,,EX, x1=38000
x2 = 2345
MPTEMP,,,,,,,,
MPTEMP,1,0
MPDATA,EX,1,,38000*6894.75
my regex is
+(?<variableName>\w+) *= *-?(?<variableValue>\d+\.?\d*)
(note the space before the first plus)
I'm looking to replace that "x1=38000" with something like "x1=100", and the "x2 = 2345" with "x2 = 200"
With the output
...
RMORE, ,
ET,MPTEMP,,,,EX, x1=100
x2 = 200
MPTEMP,,,,,,,,
...
I've created a gist containing some semi-runnable code here (it uses some stuff from our commons code base, but its followable: https://gist.github.com/Groostav/acf5b584078813e7cbe6)
The code I've got is roughly
String regex = "+(?<variableName>\\w+) *= *-?(?<variableValue>\\d+\\.?\\d*)"
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(sourceText);
while(matcher.find()){
String variableName = matcher.group("variableName");
String existingValue = matcher.group("variableValue");
int newValue;
switch(variableName){
case "x1": newValue = 100; break;
case "x2": newValue = 200; break;
default: throw new IllegalStateException();
}
matcher.appendReplacement(output, "" + newValue);
}
matcher.appendTail(output);
The regex itself works: it captures the values I need, and I can access them through matcher.group("variableName") and matcher.group("variableValue"), the issue I'm having is writing a new value back to 'variableValue', with the java regex API.
In the above example, matcher.group("variableValue") doesnt persist any state, so I cant seem to specify to the appendReplacement() method that I dont want to replace the whole line, but rather simply the second capture group.
Worth metnioning, x1 and x2 are not hard-fast runtime names, so I cant simply cheese it and write separate find and replace strings for x1 and x2. I need the runtime \w+ to find the variable name.
So I can run another regex against the result of the first, this time only capturing the value, but thats not pretty, and it would require me to probably fudge index values around with our StringBuilder/Buffer, rather than that nice index-free call to matcher.appendTail.
PS: the langauge you see above is called the "ANSYS parametric design language (APDL)", and I cant find a grammar for the thing. If any of you guys know where one is, I'd hugely appreciate it.
thanks for reading.
You can use this regex:
(\w+\s*)=(\s*\d+)
Working demo
Check the substitution section. You can use the same approach to replace the content you want as I did using capturing group index.
My Hacky solution that seems to work is to manually traverse our parse tree, down the rhs, and replace the new value. This is annoying since it requires me to refactor my regex and do that manual work, but it does do the job, and I believe its reliable:
// semi-formally, APDL seems to define:
// AssignmentExpression -> QualifiedIdentifier = Expression
// QualifiedIdentifier -> SPACE+ Identifier SPACE*
// Expression -> SPACE* Value //Value is captured as "value"
// Identifier -> [A-Za-z0-9]* //Identifier is captured as "identifier"
// Value -> [0-9]* (DOT [0-9]*)?
private static final String rValue = "\\d+(\\.\\d*)?";
private static final String rIdentifier = "(?<identifier>\\w+)";
private static final String rQualifiedIdentifier = " +" + rIdentifier + " *";
private static final String rExpression = " *-?(?<value>" + rValue + ")";
private static final String rAssignmentExpression = rQualifiedIdentifier + "=" + rExpression;
#Test
public void when_scanning_using_our_regex(){
Pattern assignmentPattern = Pattern.compile(rAssignmentExpression);
Pattern rhsPattern = Pattern.compile("=" + rExpression);
Pattern valuePattern = Pattern.compile(rValue);
Matcher assignmentMatcher = assignmentPattern.matcher(sourceText);
StringBuffer output = new StringBuffer();
int newValue = 20;
while(assignmentMatcher.find()){
String assignment = assignmentMatcher.group();
Matcher rhsMatcher = rhsPattern.matcher(assignment);
assert rhsMatcher.find() : "couldn't find an RHS in an the assignment: '" + assignment + "'?";
String oldRhs = rhsMatcher.group();
Matcher valueMatcher = valuePattern.matcher(oldRhs);
assert valueMatcher.find() : "couldn't find a value in an RHS: '" + oldRhs + "'?";
String oldValue = valueMatcher.group();
String newRhs = oldRhs.replace(oldValue, "" + newValue);
String newAssignment = assignment.replace(oldRhs, newRhs);
assignmentMatcher.appendReplacement(output, "" + newAssignment);
}
assignmentMatcher.appendTail(output);
System.out.println(output.toString());
}

How do I parse a string representing a sequence of arithmetic operations?

I am working on a personal project and I want to take in userinput that looks like this :
1.0+2.5+3--4
and format it to something like this :
1.0 + 2.5 + 3 - -4
so far I am using the .replace("+") to .replace(" + ") and doing that for all of the operands but the problem is it makes the user input into this:
1.0 + 2.5 + 3 - - 4
Is there a way that I can make it with the negative signs. I want to do this so I could parse the numbers into doubles and add and subtract them later on.
my code for it :
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class StringMan {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String check = "-a1 +a2 + a3 +-a5";
check = check.replace("--", "+");
System.out.println(check);
Pattern pattern = Pattern.compile("\\s+");
Matcher matcher = pattern.matcher(check);
boolean expr = matcher.find();
String str = matcher.replaceAll(" ");
System.out.println(str);
}
}
output is:
-a1 +a2 - a3 +-a5
-a1 +a2 - a3 +-a5
the problem is I want the output to look like this:
-a1 + a2 - a3 + -a5
In this specific case, you can handle -- by just replacing them with +:
Take input as a string from the user
Remove all white space
Replace all -- with +
Continue parsing as desired
I would recommend using regular expressions and their "group" functionality. I would actually remove all whitespace to make things easier, take it out of the equation, one less thing to deal with. And obviously I would recommend simplifying the string, replacing "--" with "+", "*+" with "*" and so on.
now you can use a regex on your cleaned up string.
Pattern firstPat = Pattern.compile("(((\\+|-)?)\\d+(.\\d+)?)");//for matching the first number, leading sign is optional
Pattern remainingPat = Pattern.compile("(\\+|-)(\\d+(.\\d+)?)");//for remaining numbers, leading sign is mandatory.
Pattern remainingPatWithExtOps = Pattern.compile("(\\*|/|\\+|-)(-?\\d+(.\\d+)?)");//for remaining numbers, accommodating multiply and divide with negative signs(positive signs should have been cleaned out)
Matcher match = firstPat.matcher(inputString);
now you can iterate through the string using the match.find() method. and then use match.group(1) to get the sign/operation, and use match.group(2) to get the number...
So...
Double firstnum;
boolean firstNumSigned = false;
if(match.find())
{
firstNum = Double.parse(match.group(0));// Parsing handles possible sign in string.
//obv check for exceptions during this and double check group num
String tmp = match.group(1);
firstNumSigned = tmp.equals("+") || tmp.equals("-");
}
else
{//no match means the input was probably invalid....
throw new IllegalArgumentException("What the heck were you thinking inputting that?!");
}
match = remainingPat.matcher(inputString);//use our other pattern for remaining numbers
if(firstNumSigned)
{
match.find();//a signed first number will cause success here, we need to ignore this since we already got the first number
}
Double tmpRemaingingNum;
String operation;
while(match.find())
{
operation = match.group(1);
tmpRemainingNum = Double.parse(match.group(2));
//Do what you want with these values now until match.find() returns false and you are done
}
PS: code is not tested, im fairly confident of the regex, but I'm not 100% sure about the grouping brackets on the first pattern.. might need to experiment
Start by replacing -- with +, which is mathematically equivalent. Or start by replacing -- with - -, which would keep - and 4 together.
Check this ,
Read both strings and integers in between operators like '*,--,-,+"
We can read both integers and characters.
public static void main(String[] args) {
// TODO Auto-generated method stub
final Pattern remainingPatWithExt=Pattern.compile("(\\p{L}\\p{M}*)[\\p{L}\\p{M}0-9^\\-.-?_+-=<>!;]*");
String check = "a1+a2+--a7+ a3 +-a5";
Matcher matcher = remainingPatWithExt.matcher(check);
while( matcher.find())
{
System.out.println(matcher.group());
//use matcher.group(0) or matcher.group(1)
}
}
output
a1
a2
a7
a3
a5

This RegEx captures wrong number of groups

I have to parse a string and capture some values:
FREQ=WEEKLY;WKST=MO;BYDAY=2TU,2WE
I want to capture 2 groups:
grp 1: 2, 2
grp 2: TU, WE
The Numbers represents intervals. TU, WE represents weekdays. I need both.
I'm using this code:
private final static java.util.regex.Pattern regBYDAY = java.util.regex.Pattern.compile(".*;BYDAY=(?:([+-]?[0-9]*)([A-Z]{2}),?)*.*");
String rrule = "FREQ=WEEKLY;WKST=MO;BYDAY=2TU,2WE";
java.util.regex.Matcher result = regBYDAY.matcher(rrule);
if (result.matches())
{
int grpCount = result.groupCount();
for (int i = 1; i < grpCount; i++)
{
String g = result.group(i);
...
}
}
grpCount == 2 - why? If I read the java documentation correctly (that little bit) I should get 5? 0 = the whole expression, 1,2,3,4 = my captures 2,2,TU and WE.
result.group(1) == "2";
I'm a C# Programmer with very little java experience so I tested the RegEx in the "Regular Expression Workbench" - a great C# Program for testing RegEx. There my RegEx works fine.
https://code.msdn.microsoft.com/RegexWorkbench
RegExWB:
.*;BYDAY=(?:([+-]?[0-9]*)([A-Z]{2}),?)*.*
Matching:
FREQ=WEEKLY;WKST=MO;BYDAY=22TU,-2WE,+223FR
1 => 22
1 => -2
1 => +223
2 => TU
2 => WE
2 => FR
You may also use this approach to increase readability and up to certain point independence from the implementation using a more common regexp subset
final Pattern re1 = Pattern.compile(".*;BYDAY=(.*)");
final Pattern re2 = Pattern.compile("(?:([+-]?[0-9]*)([A-Z]{2}),?)");
final Matcher matcher1 = re1.matcher(rrule);
if ( matcher1.matches() ) {
final String group1 = matcher1.group(1);
Matcher matcher2 = re2.matcher(group1);
while(matcher2.find()) {
System.out.println("group: " + matcher2.group(1) + " " +
matcher2.group(2));
}
}
Your regex works the same in Java as it does in C#; it's just that in Java you can only access the final capture for each group. In fact, .NET is one of only two regex flavors I know of that let you retrieve intermediate captures (Perl 6 being the other).
This is probably the simplest way to do what you want in Java:
String s= "FREQ=WEEKLY;WKST=MO;BYDAY=22TU,-2WE,+223FR";
Pattern p = Pattern.compile("(?:;BYDAY=|,)([+-]?[0-9]+)([A-Z]{2})");
Matcher m = p.matcher(s);
while (m.find())
{
System.out.printf("Interval: %5s, Day of Week: %s%n",
m.group(1), m.group(2));
}
Here's the equivalent C# code, in case you're interested:
string s = "FREQ=WEEKLY;WKST=MO;BYDAY=22TU,-2WE,+223FR";
Regex r = new Regex(#"(?:;BYDAY=|,)([+-]?[0-9]+)([A-Z]{2})");
foreach (Match m in r.Matches(s))
{
Console.WriteLine("Interval: {0,5}, Day of Week: {1}",
m.Groups[1], m.Groups[2]);
}
I'm a bit rusty, but I'll propose to "caveats". First of all, regexp(s) come in various dialects. There is a fantastic O'Reilly book about this, but there is a chance that your C# utility applies slightly different rules.
As an example, I used a similar (but different tool) and discovered that it did parse things differenty...
First of all it rejected your regexp (maybe a typo?) the initial "*" does not make sense, unless you put a dot (.) in front of it. Like this:
.*;BYDAY=(?:([+-]?[0-9]*)([A-Z]{2}),?)*.*
Now it was accepted, but it "matched" only the 2/WE part, and "skipped" the 2/TU pair.
(I suggest you read about greedy and non-greedy matching to understand this a bit better.
Therefore I updated your pattern as follows:
.*;BYDAY=(?:([+-]?[0-9]*)([A-Z]{2}),?),(?:([+-]?[0-9]*)([A-Z]{2}),?)*.*
And now it works and correctly captures 2,TU,2 and WE.
Maybe this helps?

Categories