Fixed Issue 126: Large integers formatted in scientific notation in formulas

git-svn-id: http://google-refine.googlecode.com/svn/trunk@1373 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
David Huynh 2010-09-28 04:21:44 +00:00
parent bc6f05f41b
commit e587614c22
3 changed files with 71 additions and 30 deletions

View File

@ -155,7 +155,10 @@ public class Parser {
next(true); next(true);
if (_token != null && _token.type == TokenType.Number) { if (_token != null && _token.type == TokenType.Number) {
eval = new LiteralExpr(-((NumberToken)_token).value); Number n = ((NumberToken)_token).value;
eval = new LiteralExpr(n instanceof Long ? -n.longValue() : -n.doubleValue());
next(false); next(false);
} else { } else {
throw makeException("Bad negative number"); throw makeException("Bad negative number");

View File

@ -35,9 +35,9 @@ public class Scanner {
} }
static public class NumberToken extends Token { static public class NumberToken extends Token {
final public double value; final public Number value;
public NumberToken(int start, int end, String text, double value) { public NumberToken(int start, int end, String text, Number value) {
super(start, end, TokenType.Number, text); super(start, end, TokenType.Number, text);
this.value = value; this.value = value;
} }
@ -94,34 +94,44 @@ public class Scanner {
String detail = null; String detail = null;
if (Character.isDigit(c)) { // number literal if (Character.isDigit(c)) { // number literal
double value = 0; long value = 0;
while (_index < _limit && Character.isDigit(c = _text.charAt(_index))) { while (_index < _limit && Character.isDigit(c = _text.charAt(_index))) {
value = value * 10 + (c - '0'); value = value * 10 + (c - '0');
_index++; _index++;
} }
if (_index < _limit && c == '.') { if (_index < _limit && (c == '.' || c == 'e')) {
_index++; double value2 = value;
if (c == '.') {
double division = 1;
while (_index < _limit && Character.isDigit(c = _text.charAt(_index))) {
value = value * 10 + (c - '0');
division *= 10;
_index++; _index++;
double division = 1;
while (_index < _limit && Character.isDigit(c = _text.charAt(_index))) {
value2 = value2 * 10 + (c - '0');
division *= 10;
_index++;
}
value2 /= division;
} }
value /= division; // TODO: support exponent e notation
return new NumberToken(
start,
_index,
_text.substring(start, _index),
value2
);
} else {
return new NumberToken(
start,
_index,
_text.substring(start, _index),
value
);
} }
// TODO: support exponent e notation
return new NumberToken(
start,
_index,
_text.substring(start, _index),
value
);
} else if (c == '"' || c == '\'') { } else if (c == '"' || c == '\'') {
/* /*
* String Literal * String Literal

View File

@ -29,23 +29,47 @@ public class OperatorCallExpr implements Evaluable {
if (args.length == 2) { if (args.length == 2) {
if (args[0] != null && args[1] != null) { if (args[0] != null && args[1] != null) {
if (args[0] instanceof Number && args[1] instanceof Number) { if (isIntegral(args[0]) && isIntegral(args[1])) {
long n1 = ((Number) args[0]).longValue();
long n2 = ((Number) args[1]).longValue();
if ("+".equals(_op)) { if ("+".equals(_op)) {
return ((Number) args[0]).doubleValue() + ((Number) args[1]).doubleValue(); return n1 + n2;
} else if ("-".equals(_op)) { } else if ("-".equals(_op)) {
return ((Number) args[0]).doubleValue() - ((Number) args[1]).doubleValue(); return n1 - n2;
} else if ("*".equals(_op)) { } else if ("*".equals(_op)) {
return ((Number) args[0]).doubleValue() * ((Number) args[1]).doubleValue(); return n1 * n2;
} else if ("/".equals(_op)) { } else if ("/".equals(_op)) {
return ((Number) args[0]).doubleValue() / ((Number) args[1]).doubleValue(); return n1 / n2;
} else if (">".equals(_op)) { } else if (">".equals(_op)) {
return ((Number) args[0]).doubleValue() > ((Number) args[1]).doubleValue(); return n1 > n2;
} else if (">=".equals(_op)) { } else if (">=".equals(_op)) {
return ((Number) args[0]).doubleValue() >= ((Number) args[1]).doubleValue(); return n1 >= n2;
} else if ("<".equals(_op)) { } else if ("<".equals(_op)) {
return ((Number) args[0]).doubleValue() < ((Number) args[1]).doubleValue(); return n1 < n2;
} else if ("<=".equals(_op)) { } else if ("<=".equals(_op)) {
return ((Number) args[0]).doubleValue() <= ((Number) args[1]).doubleValue(); return n1 <= n2;
}
} else if (args[0] instanceof Number && args[1] instanceof Number) {
double n1 = ((Number) args[0]).doubleValue();
double n2 = ((Number) args[1]).doubleValue();
if ("+".equals(_op)) {
return n1 + n2;
} else if ("-".equals(_op)) {
return n1 - n2;
} else if ("*".equals(_op)) {
return n1 * n2;
} else if ("/".equals(_op)) {
return n1 / n2;
} else if (">".equals(_op)) {
return n1 > n2;
} else if (">=".equals(_op)) {
return n1 >= n2;
} else if ("<".equals(_op)) {
return n1 < n2;
} else if ("<=".equals(_op)) {
return n1 <= n2;
} }
} }
@ -86,4 +110,8 @@ public class OperatorCallExpr implements Evaluable {
return sb.toString(); return sb.toString();
} }
private boolean isIntegral(Object n) {
return n instanceof Long || n instanceof Integer;
}
} }