blob: 9cd72240f4ee5620f24fa0d50639098c8d74a672 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.imaging.common;
import java.text.DecimalFormat;
import java.text.NumberFormat;
public class RationalNumber extends Number
{
private static final long serialVersionUID = -1;
public final int numerator;
public final int divisor;
public RationalNumber(int numerator, int divisor)
{
this.numerator = numerator;
this.divisor = divisor;
}
public static final RationalNumber factoryMethod(long n, long d)
{
// safer than constructor - handles values outside min/max range.
// also does some simple finding of common denominators.
if (n > Integer.MAX_VALUE || n < Integer.MIN_VALUE
|| d > Integer.MAX_VALUE || d < Integer.MIN_VALUE)
{
while ((n > Integer.MAX_VALUE || n < Integer.MIN_VALUE
|| d > Integer.MAX_VALUE || d < Integer.MIN_VALUE)
&& (Math.abs(n) > 1) && (Math.abs(d) > 1))
{
// brutal, inprecise truncation =(
// use the sign-preserving right shift operator.
n >>= 1;
d >>= 1;
}
if (d == 0)
throw new NumberFormatException("Invalid value, numerator: "
+ n + ", divisor: " + d);
}
long gcd = gcd(n, d);
d = d / gcd;
n = n / gcd;
return new RationalNumber((int) n, (int) d);
}
/**
* Return the greatest common divisor
*/
private static long gcd(long a, long b)
{
if (b == 0)
return a;
else
return gcd(b, a % b);
}
public RationalNumber negate()
{
return new RationalNumber(-numerator, divisor);
}
@Override
public double doubleValue()
{
return (double) numerator / (double) divisor;
}
@Override
public float floatValue()
{
return (float) numerator / (float) divisor;
}
@Override
public int intValue()
{
return numerator / divisor;
}
@Override
public long longValue()
{
return (long) numerator / (long) divisor;
}
public boolean isValid()
{
return divisor != 0;
}
private static final NumberFormat nf = DecimalFormat.getInstance();
@Override
public String toString()
{
if (divisor == 0)
return "Invalid rational (" + numerator + "/" + divisor + ")";
if ((numerator % divisor) == 0)
return nf.format(numerator / divisor);
return numerator + "/" + divisor + " ("
+ nf.format((double) numerator / divisor) + ")";
}
public String toDisplayString()
{
if ((numerator % divisor) == 0)
return "" + (numerator / divisor);
NumberFormat nf = DecimalFormat.getInstance();
nf.setMaximumFractionDigits(3);
return nf.format((double) numerator / (double) divisor);
}
}