Advertisement
Guest User

Untitled

a guest
Dec 7th, 2016
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.50 KB | None | 0 0
  1. /*************************************************
  2. * A class for representing rational numbers.
  3. * @author Edvin Lam
  4. * @author Lucas Ravens
  5. * @assignment 43, Lab 2
  6. * @version 0.2
  7. ************************************************/
  8.  
  9. public class RatNum {
  10. private int numerator;
  11. private int denominator = 1;
  12.  
  13. /**
  14. * Creates a new default RatNum object with a numerator of 0 and a denominator of 1.
  15. */
  16. public RatNum(){
  17. numerator = 0;
  18. denominator = 1;
  19. }
  20. /**
  21. * Creates a new RatNum object with a specified numerator and a denominator of 1.
  22. * @param a The numerator of the rational number.
  23. */
  24. public RatNum(int a){
  25. numerator = a;
  26. }
  27. /**
  28. * Creates a new RatNum object with a specified numerator and denominator.
  29. * @param a The numerator of the rational number.
  30. * @param b The denominator of the rational number.
  31. */
  32.  
  33. public RatNum(int a, int b){
  34. if (b == 0) throw new NumberFormatException("Denominator = 0");
  35. numerator = a/gcd(a,b);
  36. denominator = b/gcd(a,b);
  37. if (numerator < 0 && denominator < 0) {
  38. numerator = Math.abs(numerator);
  39. denominator = Math.abs(denominator);
  40. } else if (denominator < 0) {
  41. denominator = (-1)*denominator;
  42. numerator = (-1)*numerator;
  43. }
  44. }
  45. /**
  46. * Creates a copy of an existing RatNum object.
  47. * @param r The RatNum object to copy.
  48. */
  49. public RatNum(RatNum r){
  50. numerator = r.getNumerator();
  51. denominator = r.getDenominator();
  52. }
  53.  
  54. /**
  55. * Creates a new RatNum object from a string.
  56. * @param s The rational number in the form of "a/b", where a and b are integers.
  57. */
  58. public RatNum(String s){
  59. this((RatNum)parse(s));
  60. }
  61.  
  62. /**
  63. * Returns the numerator as an integer.
  64. * @return Numberator as an integer.
  65. */
  66. public int getNumerator(){
  67. return numerator;
  68. }
  69.  
  70. /**
  71. * Returns the denominator as an integer.
  72. * @return Denominator as integer.
  73. */
  74. public int getDenominator(){
  75. return denominator;
  76. }
  77.  
  78. /**
  79. * Creates a string representation of this RatNum.
  80. * Overrides toString.
  81. * @return a string representation of this RatNum.
  82. */
  83. public String toString() {
  84. return numerator+"/"+denominator;
  85. }
  86.  
  87. /**
  88. * Creates a double representation of this RatNum.
  89. * Not to be used in any calculations, as it probably would result in rounding errors.
  90. * Instead to be used to represent the final RatNum, after calculations.
  91. * @return a double representation of this RatNum
  92. */
  93. public double toDouble() {
  94. return (double)numerator/denominator;
  95. }
  96.  
  97. /**
  98. * Creates a copy of this RatNum as a new object.
  99. * @return a new RatNum object.
  100. * @throws CloneNotSupportedException if object isn't a RatNum object.
  101. */
  102. public Object clone()throws CloneNotSupportedException {
  103. return super.clone();
  104. }
  105.  
  106. /**
  107. * Method for addition of two RatNum objects.
  108. * @param r, the RatNum object to perform the addition with.
  109. * @return a new RatNum object.
  110. */
  111. public RatNum add(RatNum r) {
  112. int numerator2 = r.getNumerator();
  113. int denominator2 = r.getDenominator();
  114. int newDenominator = denominator*denominator2;
  115. int newNumerator = numerator*denominator2+numerator2*denominator;
  116. return new RatNum(newNumerator, newDenominator);
  117. }
  118.  
  119. /**
  120. * Method for subtraction of two RatNum objects.
  121. * @param r, the RatNum object to perform the subtraction with.
  122. * @return a new RatNum object.
  123. */
  124. public RatNum sub(RatNum r) {
  125. int numerator2 = r.getNumerator();
  126. int denominator2 = r.getDenominator();
  127. int newDenominator = denominator*denominator2;
  128. int newNumerator = numerator*denominator2-numerator2*denominator;
  129. return new RatNum(newNumerator, newDenominator);
  130. }
  131.  
  132. /**
  133. * Method for multiplying two RatNum objects.
  134. * @param r, the RatNum object to perform the multiplication with.
  135. * @return a new RatNum object.
  136. */
  137. public RatNum mul(RatNum r) {
  138. int numerator2 = r.getNumerator();
  139. int denominator2 = r.getDenominator();
  140. int newDenominator = denominator*denominator2;
  141. int newNumerator = numerator*numerator2;
  142. return new RatNum(newNumerator, newDenominator);
  143. }
  144.  
  145. /**
  146. * Method for dividing two RatNum objects.
  147. * @param r, the RatNum object to perform the division with.
  148. * @return a new RatNum object.
  149. */
  150. public RatNum div(RatNum r) {
  151. int numerator2 = r.getNumerator();
  152. int denominator2 = r.getDenominator();
  153. int newDenominator = denominator*numerator2;
  154. int newNumerator = numerator*denominator2;
  155. return new RatNum(newNumerator, newDenominator);
  156. }
  157.  
  158. /**
  159. * Method for comparing two RatNum objects, to determine whether they are equal.
  160. * @param r, the RatNum object to compare with.
  161. * @return a boolean, true if equal.
  162. */
  163. public boolean equals(Object r) {
  164. if (r == null || this.getClass() != r.getClass() ){
  165. return false;
  166. } else {
  167. RatNum tmp = (RatNum)r;
  168. return(tmp.getNumerator() == numerator && tmp.getDenominator() == denominator);
  169. }
  170. }
  171.  
  172. /**
  173. * Method for comparing two RatNum objects, to determine whether the input RatNum is smaller that its argument r.
  174. * @param r, the RatNum object to compare with.
  175. * @return a boolean, true if input RatNum is smaller than r.
  176. */
  177. public boolean lessThan(RatNum r) {
  178. return (r.toDouble() > toDouble());
  179. }
  180.  
  181. /**
  182. * Method for calculating the greatest common divisor (GCD) of two integers.
  183. * @param a, integer for which the GCD is to be found.
  184. * @param b, integer for which the GCD is to be found -
  185. * @return an integer, the GCD.
  186. * @throws IllegalArgumentException is thrown if a and b are both 0.
  187. */
  188. public static int gcd(int a, int b) {
  189. a = Math.abs(a);
  190. b = Math.abs(b);
  191. if (a == 0 && b == 0) {
  192. IllegalArgumentException e = new IllegalArgumentException();
  193. throw e;
  194. } else if (b == 0) {
  195. return a;
  196. } else {
  197. if (a%b == 0) {
  198. return b;
  199. } else {
  200. return(gcd(b,a%b));
  201. }
  202. }
  203. }
  204.  
  205. /**
  206. * Method for parsing string input.
  207. * Reads string input. If input is valid, method will return a RatNum object.
  208. * @param s, a string with input.
  209. * @return a RatNum object, if input is valid.
  210. * @throws NumberFormatException if input is invalid.
  211. */
  212. public static RatNum parse(String s){
  213. int slash = -1; // The initial value of slash is set to -1 to handle rational number without '/'
  214. int a = 1;
  215. int b = 1;
  216. int slashCounter = 0;
  217. for(int i = 0; i < s.length(); i++) {
  218. if(s.charAt(i) == '/'){
  219. slash = i;
  220. slashCounter++;
  221. if(slashCounter > 1) { // To check for silly input
  222. NumberFormatException e = new NumberFormatException();
  223. throw e;
  224. }
  225. } else if (Character.isDigit(s.charAt(i)) == false && s.charAt(i) != '-') {
  226. NumberFormatException e = new NumberFormatException();
  227. throw e;
  228. }
  229. }
  230. if (slash == -1) {
  231. a = Integer.parseInt(s);
  232. } else {
  233. a = Integer.parseInt(s.substring(0,slash));
  234. b = Integer.parseInt(s.substring(slash+1, s.length()));
  235. }
  236. return new RatNum(a,b);
  237. }
  238.  
  239. /**
  240. * Method for evaluating string input containing RatNum-compliant rational numbers.
  241. * Uses previous methods for handling addition, subtraction, multiplication, division and comparing.
  242. * @param str, a string containing input to be evaluated.
  243. * @return string, containing the calculated RatNum.
  244. */
  245. public static String evalExpr(String str){
  246. //PARSE TWO RATIONAL NUMBERS//
  247. int endFirstRat = -1;
  248. int startSecondRat = -1;
  249. int endSecondRat = -1;
  250. boolean twoRats = false;
  251. if(str.charAt(0) == '-' || Character.isDigit(str.charAt(0))){
  252. for(int i = 1; i < str.length(); i++){
  253. if(endFirstRat == -1 && str.charAt(i) == ' ' && Character.isDigit(str.charAt(i-1))){
  254. endFirstRat = i; //Finds the end of the first Rat
  255. //System.out.println("First: "+i+" substring: "+str.substring(0, endFirstRat));
  256. } else if(endFirstRat != -1 && startSecondRat == -1 && (Character.isDigit(str.charAt(i)) || (str.charAt(i) == '-') && Character.isDigit(str.charAt(i+1)) )){ //The second number starts here
  257. startSecondRat = i; //Finds the start of the second Rat
  258. //System.out.println("Second: "+i+" substring: "+str.substring(startSecondRat));
  259. } else if(endFirstRat != -1 && startSecondRat != -1 && endSecondRat == -1 && Character.isDigit(str.charAt(i-1)) && str.charAt(i) == ' '){
  260. endSecondRat = i; //Finds the end of the second Rat (if the string continues after the second Rat)
  261. twoRats = true;
  262. } else if(twoRats && (Character.isDigit(str.charAt(i)) || str.charAt(i) == '-')){ //Checks if there are more than two Rats
  263. return "evalExpr error(1): in RatNum expression, too many or too few terms";
  264. }
  265. }
  266. if(endSecondRat == -1) endSecondRat = str.length(); //Unnecessary code if it's declared as str.length() instead
  267. if(endFirstRat == -1 || startSecondRat == -1){ //If the first Rat never ends or if the second Rat never starts
  268. return "evalExpr error(1): in RatNum expression, too many or too few terms";
  269. } else { //Two substrings have been found by this point
  270. int slashCounter = 0; //Starts checking if the first Rat is valid
  271. int slashPosRat1 = -1; //Stores the position of the /
  272. int slashPosRat2 = -1;
  273. for(int i = 1; i < endFirstRat; i++){ //Starts at 1 to avoid index out of bounds; shouldn't affect the program
  274. if((str.charAt(i) == '-' && str.charAt(i-1) != '/') || (!Character.isDigit(str.charAt(i)) && str.charAt(i) != '-' && str.charAt(i) != '/')){
  275. return "evalExpr error(4): NumberFormatException: "; //Finds invalid Rats, e.g. 3-3/5,
  276. }
  277. if(str.charAt(i) == '/' && Character.isDigit(str.charAt(i-1))){
  278. slashCounter++;
  279. slashPosRat1 = i;
  280. if(slashCounter > 1) return "evalExpr error(4): NumberFormatException: ";
  281. }else if(str.charAt(i) == '/' && !Character.isDigit(str.charAt(i-1))){ //Checks if the character before the / is a digit
  282. return "evalExpr error(4): NumberFormatException: ";
  283. }
  284. }
  285. slashCounter = 0; //Resets the slash counter and starts checking the second Rat
  286. for(int i = startSecondRat+1; i < endSecondRat; i++){ //Already knows the first character is valid, so it gets skipped
  287. if((str.charAt(i) == '-' && str.charAt(i-1) != '/') || (!Character.isDigit(str.charAt(i)) && str.charAt(i) != '-' && str.charAt(i) != '/')){
  288. return "evalExpr error(4): NumberFormatException: ";
  289. }
  290. if(str.charAt(i) == '/'){
  291. slashCounter++;
  292. slashPosRat2 = i;
  293. //System.out.println(slashPosRat2);
  294. if(slashCounter > 1) return "evalExpr error(4): NumberFormatException: ";
  295. }else if(str.charAt(i) == '/' && !Character.isDigit(str.charAt(i-1))){ //Checks if the character before the / is a digit
  296. return "evalExpr error(4): NumberFormatException: ";
  297. }
  298. if(!Character.isDigit(str.charAt(endSecondRat-1))){ //Checks if the last character in the second Rat is a digit
  299. return "evalExpr error(4): NumberFormatException: ";
  300. }
  301. }
  302. if(slashPosRat1 != -1){ //Checks if the denominator in the first Rat is 0
  303. if(Integer.parseInt(str.substring(slashPosRat1+1, endFirstRat)) == 0){
  304. //System.out.println(str.substring(slashPosRat1+1, endFirstRat));
  305. return "evalExpr error(4): NumberFormatException: Denominator = 0";
  306. }
  307. }
  308. if(slashPosRat2 != -1){ //Checks if the denominator in the second Rat is 0
  309. if(Integer.parseInt(str.substring(slashPosRat2+1, endSecondRat)) == 0){
  310. //System.out.println(str.substring(slashPosRat2+1, endSecondRat));
  311. return "evalExpr error(4): NumberFormatException: Denominator = 0";
  312. }
  313. }
  314. }
  315. } else return "evalExpr error(4): NumberFormatException: ";
  316. //PARSE THE OPERATOR//
  317. String operator = str.substring(endFirstRat, startSecondRat);
  318. //System.out.println(operator);
  319. //System.out.println("we're here");
  320. RatNum firstRat = new RatNum(str.substring(0, endFirstRat));
  321. //System.out.println(startSecondRat);
  322. //System.out.println(endSecondRat);
  323. RatNum secondRat = new RatNum(str.substring(startSecondRat, endSecondRat));
  324. //System.out.println(firstRat+operator+secondRat);
  325. //ACTIONS, BARRING ANY ERRORS
  326. if(operator.equals(" + ")) return ""+firstRat.add(secondRat);
  327. else if(operator.equals(" - ")) return ""+firstRat.sub(secondRat);
  328. else if(operator.equals(" * ")) return ""+firstRat.mul(secondRat);
  329. else if(operator.equals(" / ") && secondRat.toDouble() != 0.0) return ""+firstRat.div(secondRat);
  330. else if(operator.equals(" / ") && secondRat.toDouble() == 0.0) return "evalExpr error(4): NumberFormatException: Denominator = 0";
  331. else if(operator.equals(" < ")) return ""+firstRat.lessThan(secondRat);
  332. else if(operator.equals(" = ")) return ""+firstRat.equals(secondRat);
  333. else return "evalExpr error(2): operator wrong or missing";
  334. }
  335.  
  336.  
  337. /*
  338. public static String evalExpr(String str){
  339. int spaceCounter = 0;
  340. int operatorPos = -1;
  341. int firstSpace = -1;
  342. int secondSpace = -1;
  343. int numOfNumerators = 0;
  344. if (Character.isDigit(str.charAt(0))) {
  345. numOfNumerators++;
  346. } else if (str.charAt(0) != '-') {
  347. return "evalExpr error(4): NumberFormatException: ";
  348. }
  349. for (int i = 0; i < str.length(); i++) { // Counts the number of terms
  350. if (Character.isDigit(str.charAt(i)) && i != 0 && ((str.charAt(i-1) == '-' && str.charAt(i-2) != '/') || str.charAt(i-1) != '/') && (!Character.isDigit(str.charAt(i-1)) || str.charAt(i-1) == '-')) {
  351. numOfNumerators++;
  352. System.out.println(numOfNumerators);
  353. }
  354. }
  355. if (numOfNumerators != 2) { //TODO: Change the number of terms to two
  356. return "evalExpr error(1) in ratNum expression, too few or too many terms";
  357. }
  358.  
  359.  
  360. for (int i = 0; i < str.length(); i++) {
  361. if (str.charAt(i) == ' ') {
  362. spaceCounter++;
  363. if (spaceCounter == 1){
  364. firstSpace = i;
  365. } else if (spaceCounter == 2){
  366. secondSpace = i;
  367. operatorPos = i-1;
  368. } else if (spaceCounter > 2){
  369. return "evalExpr error(5): Unknown error";
  370. }
  371. }
  372. }
  373. if (secondSpace - firstSpace != 2) {
  374. return "evalExpr error(2): operator wrong or missing";
  375. }
  376. if (spaceCounter == 0) {
  377. return "evalExpr error(5): Unknown error";
  378. }
  379. if (str.charAt(operatorPos) != '/') {
  380. int slashCounter = 0;
  381. for (int i = 0; i < str.length(); i++) {
  382. if (str.charAt(i) == '/') {
  383. slashCounter++;
  384. if (slashCounter > 2) {
  385. return ("evalExpr error(4): NumberFormatException: ");//+ e.getMessage());
  386. }
  387. }
  388. }
  389. }
  390.  
  391. if (str.charAt(operatorPos) == '/') {
  392. int slashCounter = 0;
  393. for (int i = 0; i < str.length(); i++) {
  394. if (str.charAt(i) == '/') {
  395. slashCounter++;
  396. if (slashCounter > 3) {
  397. return ("evalExpr error(4): NumberFormatException: ");//+ e.getMessage());
  398. }
  399. }
  400. }
  401. String first = str.substring(0,firstSpace);
  402. String second = str.substring(secondSpace+1,str.length());
  403. RatNum firstRN = new RatNum(first);
  404. RatNum secondRN = new RatNum(second);
  405. if (secondRN.getNumerator() == 0){
  406. return "evalExpr error(4): NumberFormatException";
  407. } else {
  408. return ""+firstRN.div(secondRN);
  409. }
  410. } else if (str.charAt(operatorPos) == '*') {
  411. RatNum firstRN = new RatNum(str.substring(0,firstSpace));
  412. RatNum secondRN = new RatNum(str.substring(secondSpace+1,str.length()));
  413. return ""+firstRN.mul(secondRN);
  414. } else if (str.charAt(operatorPos) == '+') {
  415. RatNum firstRN = new RatNum(str.substring(0,firstSpace));
  416. RatNum secondRN = new RatNum(str.substring(secondSpace+1,str.length()));
  417. return ""+firstRN.add(secondRN);
  418. } else if (str.charAt(operatorPos) == '-') {
  419. RatNum firstRN = new RatNum(str.substring(0,firstSpace));
  420. RatNum secondRN = new RatNum(str.substring(secondSpace+1,str.length()));
  421. return ""+firstRN.sub(secondRN);
  422. } else if (str.charAt(operatorPos) == '<') {
  423. RatNum firstRN = new RatNum(str.substring(0,firstSpace));
  424. RatNum secondRN = new RatNum(str.substring(secondSpace+1,str.length()));
  425. return ""+firstRN.lessThan(secondRN);
  426. } else if (str.charAt(operatorPos) == '=') {
  427. RatNum firstRN = new RatNum(str.substring(0,firstSpace));
  428. RatNum secondRN = new RatNum(str.substring(secondSpace+1,str.length()));
  429. return ""+firstRN.equals(secondRN);
  430. } else {
  431. return "evalExpr error(2): operator wrong or missing";
  432. }
  433. }
  434. */
  435. public static void main(String[] args) {
  436. System.out.println(evalExpr("5 + 7/0"));
  437. }
  438. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement