0

I creating a program where it takes a base unit in the metric system. (Say grams.) And then when you select a prefix changes it to the equivalent amount. (Such as 1000 grams when you select Kilo would change it to 1 Kilogram.)

Problem is when I run the code it'll always end up as zero, which makes me think I'm manipulating the BigIntegers wrong. (I'm using VERY large numbers due to some prefixes being very small or very large beyond the usual long number.)

Here is the code:

import java.util.Scanner;
import java.math.BigInteger;

public class BaseMetricUnits {

public static void main(String[] args) {
    // TODO Auto-generated method stub
    System.out.println("Hello, World!");
    float meter = 1;
    float kilogram = 1;
    float second = 1;
    float ampere = 1;
    float kelvin = 1;
    float mole = 1;
    float candela = 1;
    PrefixConverter();
}
public static void PrefixConverter() 
{

    BigInteger Yocto = BigInteger.valueOf((long) 0.00000000000000000000000);
    BigInteger Zepto =  BigInteger.valueOf((long) 0.000000000000000000001);
    BigInteger Atto = BigInteger.valueOf((long) 0.000000000000000001);
    BigInteger Femto = BigInteger.valueOf((long) 0.000000000000001);
    BigInteger Pico = BigInteger.valueOf((long)0.000000000001);
    BigInteger Nano = BigInteger.valueOf((long)0.000000001);
    BigInteger Micro = BigInteger.valueOf((long)0.000001);
    BigInteger Milli = BigInteger.valueOf((long)0.001);
    BigInteger Centi = BigInteger.valueOf((long)0.01);
    BigInteger Deci = BigInteger.valueOf((long)0.1);
    BigInteger Deca = BigInteger.valueOf((long)10);
    BigInteger Hecto = BigInteger.valueOf((long)100);
    BigInteger Kilo = BigInteger.valueOf((long)1000);
    BigInteger Mega = BigInteger.valueOf((long)1000000);
    BigInteger Giga = BigInteger.valueOf((long)1000000000);
    BigInteger Tera = new BigInteger("1000000000000");
    BigInteger Peta = new BigInteger("1000000000000000");
    BigInteger Exa = new BigInteger("1000000000000000000");
    BigInteger Zetta = new BigInteger("1000000000000000000000");
    BigInteger Yotta = new BigInteger("1000000000000000000000000");

    long Amount;
    double Prefix; 
    String Units = "";
    BigInteger translatedResult;
    BigInteger Result;

    Scanner inputDevice = new Scanner(System.in);
    System.out.print("Please enter the type of unit to be used. (meters, grams, etc.) >> ");
    Units = inputDevice.next();
    System.out.print("Please enter an amount to be translated >> ");
    Amount = inputDevice.nextLong();
    System.out.print("Please choose one of the following Prefixes to translate to. ");
    System.out.print(" 1 - Yocto ");
    System.out.print(" 2 - Zepto ");
    System.out.print(" 3 - Atto ");
    System.out.print(" 4 - Femto ");
    System.out.print(" 5 - Pico ");
    System.out.print(" 6 - Nano ");
    System.out.print(" 7 - Micro ");
    System.out.print(" 8 - Milli ");
    System.out.print(" 9 - Centi ");
    System.out.print(" 10 - Deci ");
    System.out.print(" 11 - Deca ");
    System.out.print(" 12 - Hecto ");
    System.out.print(" 13 - Kilo ");
    System.out.print(" 14 - Mega ");
    System.out.print(" 15 - Giga ");
    System.out.print(" 16 - Tera ");
    System.out.print(" 17 - Peta ");
    System.out.print(" 18 - Exa ");
    System.out.print(" 19 - Zetta ");
    System.out.print(" 20 - Yotta ") ;
    Prefix = inputDevice.nextDouble();

     if(Prefix == 1)
     {
        Result = Yocto.multiply(BigInteger.valueOf(Amount));
        translatedResult = Yocto.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Yocto" + Units + ".");
     }
     if(Prefix == 2)
     {
        Result = Zepto.multiply(BigInteger.valueOf(Amount));
        translatedResult = Zepto.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Zepto" + Units + ".");
     }
     if(Prefix == 3)
     {
        Result = Atto.multiply(BigInteger.valueOf(Amount));
        translatedResult = Atto.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Atto" + Units + ".");
     }
     if(Prefix == 4)
     {
        Result = Femto.multiply(BigInteger.valueOf(Amount));
        translatedResult = Femto.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Femto" + Units + ".");
     }
     if(Prefix == 5)
     {
        Result = Pico.multiply(BigInteger.valueOf(Amount));
        translatedResult = Pico.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Pico" + Units + ".");
     }
     if(Prefix == 6)
     {
        Result = Nano.multiply(BigInteger.valueOf(Amount));
        translatedResult = Nano.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Nano" + Units + ".");
     }
     if(Prefix == 7)
     {
        Result = Micro.multiply(BigInteger.valueOf(Amount));
        translatedResult = Micro.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Micro" + Units + ".");
     }
     if(Prefix == 8)
     {
        Result = Milli.multiply(BigInteger.valueOf(Amount));
        translatedResult = Milli.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Milli" + Units + ".");
     }
     if(Prefix == 9)
     {
        Result = Centi.multiply(BigInteger.valueOf(Amount));
        translatedResult = Centi.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Centi" + Units + ".");
     }
     if(Prefix == 10)
     {
        Result = Deci.multiply(BigInteger.valueOf(Amount));
        translatedResult = Deci.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Deci" + Units + ".");
     }
     if(Prefix == 11)
     {
        Result = Deca.multiply(BigInteger.valueOf(Amount));
        translatedResult = Deca.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Deca" + Units + ".");
     }
     if(Prefix == 12)
     {
        Result = Hecto.multiply(BigInteger.valueOf(Amount));
        translatedResult = Hecto.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Hecto" + Units + ".");
     }
     if(Prefix == 13)
     {
        Result = Kilo.multiply(BigInteger.valueOf(Amount));
        translatedResult = Kilo.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Kilo" + Units + ".");
     }
     if(Prefix == 14)
     {
        Result = Mega.multiply(BigInteger.valueOf(Amount));
        translatedResult = Mega.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Mega" + Units + ".");
     }
     if(Prefix == 15)
     {
        Result = Giga.multiply(BigInteger.valueOf(Amount));
        translatedResult = Giga.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units +  " which translates to " + translatedResult + "Giga" + Units + ".");
     }
     if(Prefix == 16)
     {
        Result = Tera.multiply(BigInteger.valueOf(Amount));
        translatedResult = Tera.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Tera" + Units + ".");
     }  
     if(Prefix == 17)
     {
        Result = Peta.multiply(BigInteger.valueOf(Amount));
        translatedResult = Peta.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Peta" + Units + ".");
     }
     if(Prefix == 18)
     {
        Result = Exa.multiply(BigInteger.valueOf(Amount));
        translatedResult = Exa.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Exa" + Units + ".");
     }
     if(Prefix == 19)
     {
        Result = Zetta.multiply(BigInteger.valueOf(Amount));
        translatedResult = Zetta.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Zetta" + Units + ".");
     }
     if(Prefix == 20)
     {
        Result = Yotta.multiply(BigInteger.valueOf(Amount));
        translatedResult = Yotta.divide(BigInteger.valueOf(Amount));
        System.out.println("You have " + Result + " " + Units + " which translates to " + translatedResult + "Yotta" + Units + ".");
     }
     else
     {
        System.out.println("Not a valid input.");
     }
    }
}

Thanks for your help.

Balwinder Singh
  • 2,272
  • 5
  • 23
  • 34
dpolaristar
  • 69
  • 1
  • 8
  • 2
    `(long) 0.000000000000000000001 == 0L` etc. The cast basically takes the integer part of the number. Is there a good reason why you didn't use `"0.000000000000000000001"` like you did for Tera, Peta etc? Or `BigInteger.ONE.shiftRight/Left`? – Andy Turner Oct 05 '15 at 22:38
  • I just realized I mixed the multiply and divide methods up, that being said some answers still come up as 0. – dpolaristar Oct 05 '15 at 22:40
  • @AndyTurner on the smaller numbers like the first one BigInteger Yocto for example it throws me these weird errors. Exception in thread "main" java.lang.NumberFormatException: For input string: ".00000" at java.lang.NumberFormatException.forInputString(Unknown Source) at java.lang.Integer.parseInt(Unknown Source) at java.math.BigInteger.(Unknown Source) at java.math.BigInteger.(Unknown Source) at BaseMetricUnits.PrefixConverter(BaseMetricUnits.java:21) at BaseMetricUnits.main(BaseMetricUnits.java:16) Like these. – dpolaristar Oct 05 '15 at 22:44
  • 2
    Why are you using BigInteger rather than BigDecimal for fractions? BigInteger can only store integers. – Patricia Shanahan Oct 05 '15 at 22:49
  • And if you use the shift methods? – Andy Turner Oct 05 '15 at 22:49
  • @PatriciaShanahan for not spotting that. – Andy Turner Oct 05 '15 at 22:50
  • @PatriciaShanahan If you look down in the code it spits out an answer as "Result" and "translatedResult." Unless I can think of a way to make it either be a BigInteger or a BigDecimal based off the context the final answer can be one or the other. I'm worried if a user want to try to translate one gram into say a Yottagram and then the BigInteger answer will get caught up in an error trying to store a decimal and vica versa. – dpolaristar Oct 05 '15 at 23:01
  • @AndyTurner what shift methods? – dpolaristar Oct 05 '15 at 23:02
  • @dpolaristar You can't make a BigInteger do a BigDecimal's job. If the answer is an integer and you want it reported as such, you can use the BigDecimal's toBigInteger or toBigIntegerExact. – Patricia Shanahan Oct 05 '15 at 23:03
  • Is there a way to dynamically make it the Result or translatedResult store the answer as a BigDecimal or BigInteger depending on what answer comes out for the math. (A user might try to turn 1 gram into 0.00000000000000000000000 Yotta gram for example which would make it inappropriate to store as a BigInteger, but It also would be equally inappriopriate to store 1000000000000000000000000 grams as 1 Yocto gram as a BigDecimal as well. While most users might use common sense to avoid triggering this, other users might try to break the program. – dpolaristar Oct 05 '15 at 23:13
  • Now I get an error where when It goes Non-terminating decimal expansion; no exact representable decimal result. at java.math.BigDecimal.divide(Unknown Source) When I try to do arithmetic. – dpolaristar Oct 06 '15 at 16:21
  • @dpolaristar The BigDecimal error message is a new issue. Before posting a question about it, reread the BigDecimal API documentation to see if you can work out what is going wrong. If you do post, include a minimal failing program illustrating the problem. – Patricia Shanahan Oct 07 '15 at 01:07

1 Answers1

1

BigInteger can only store integers, and so is not a suitable data type for this application. I strongly recommend replacing it with BigDecimal.

You should also use string representations of the fractions to initialize:

  BigDecimal Zepto =  new BigDecimal("0.000000000000000000001");
  BigDecimal Atto = new BigDecimal("0.000000000000000001");
  BigDecimal Femto = new BigDecimal("0.000000000000001");
  BigDecimal Pico = new BigDecimal("0.000000000001");
  BigDecimal Nano = new BigDecimal("0.000000001");

Comments on this answer and on the question indicate a concern with using BigDecimal to store the larger numbers. This program illustrates the fact that it is not an issue:

import java.math.BigDecimal;

public class Test {
  public static void main(String[] args) {
    BigDecimal googol = new BigDecimal("1e100");
    System.out.println(googol);
    System.out.println(googol.add(BigDecimal.ONE));
  }
}

Output:

1E+100
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75
  • If you look down in the code it spits out an answer as "Result" and "translatedResult." Unless I can think of a way to make it either be a BigInteger or a BigDecimal based off the context the final answer can be one or the other. I'm worried if a user want to try to translate one gram into say a Yottagram and then the BigInteger answer will get caught up in an error trying to store a decimal and vica versa. – – dpolaristar Oct 05 '15 at 23:02
  • 1
    Why do you ever want Result to be a BigInteger? That would lose data if the answer is not an integer. On the other hand, BigDecimal can store anything BigInteger can store. – Patricia Shanahan Oct 05 '15 at 23:07
  • So I can store all the numbers even the big ones as BigDecimal? I didn't know that. – dpolaristar Oct 05 '15 at 23:15
  • @dpolaristar Yes, BigDecimal can handle very big numbers, bigger than you are using. A BigDecimal is really a BigInteger scaled by a power of ten to handle decimal fractions as well as integers. – Patricia Shanahan Oct 05 '15 at 23:19