if statements possibly not working - android

I have a fairly simple calculator with 2 tabs, the tabs appear to be working fine with the first tab calculating as it should, but the calculating for the second tab keeps throwing the catch error.
In the 2nd tab, I have 2 if statements, which checks to see which edittext field contains data. Depending on which contains data to what calculation it does.
Below is the code for when my button is pressed I have put together, it could probably be streamlined but just I'm an amature so go easy on me.
Any advice to get this working please?
calculate.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View view) {
if ( tabs.getCurrentTab() == 0) {
try {
if (d.getText().toString().trim().length() == 0) {
a1 = a.getText().toString();
double a2 = Double.parseDouble(a1);
b1 = b.getText().toString();
double b2 = Double.parseDouble(b1);
double sum = (a2 * b2) / 10000;
double total = Math.round((sum) * 10) / 10.0;
answer.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer.setText(String.valueOf("Total Area Allocation = " + total + " ha"));
} else if (d.getText().toString().trim().length() >= 1) {
a1 = a.getText().toString();
double a2 = Double.parseDouble(a1);
b1 = b.getText().toString();
double b2 = Double.parseDouble(b1);
d1 = d.getText().toString();
double d2 = Double.parseDouble(d1);
double sum = (a2 * b2) / 10000;
double sum2 = (a2 * b2) / d2;
double total = Math.round((sum) * 10) / 10.0;
double total2 = Math.round((sum2) * 10) / 10.0;
answer.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer.setText(String.valueOf("Total Area Allocation = " + total + " ha"));
answer2.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer2.setText(String.valueOf("Set break " + total2 + " m"));
}
} catch (Exception e) {
answer.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer.setText("Enter values in input fields");
}
}
if (tabs.getCurrentTab() == 1) {
try {
if (ff.getText().toString().trim().length() == 0) {
aa1 = aa.getText().toString();
double aa2 = Double.parseDouble(aa1);
bb1 = bb.getText().toString();
double bb2 = Double.parseDouble(bb1);
cc1 = cc.getText().toString();
double cc2 = Double.parseDouble(cc1);
dd1 = dd.getText().toString();
double dd2 = Double.parseDouble(dd1);
ee1 = ee.getText().toString();
double ee2 = Double.parseDouble(ee1);
if (ee.getText().toString().trim().length() == 0){
double sum = (aa2 * bb2)/(cc2 - dd2);
double total = Math.round((sum) * 10) / 10.0;
answer.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer.setText(String.valueOf("Total Area Allocation = " + total + " ha"));
}
else if (cc.getText().toString().trim().length() == 0){
double sum = (aa2 * bb2)/ee2;
double total = Math.round((sum) * 10) / 10.0;
answer.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer.setText(String.valueOf("Total Area Allocation = " + total + " ha"));
}
} else if (ff.getText().toString().trim().length() >= 1) {
aa1 = aa.getText().toString();
double aa2 = Double.parseDouble(aa1);
bb1 = bb.getText().toString();
double bb2 = Double.parseDouble(bb1);
cc1 = cc.getText().toString();
double cc2 = Double.parseDouble(cc1);
dd1 = dd.getText().toString();
double dd2 = Double.parseDouble(dd1);
ee1 = ee.getText().toString();
double ee2 = Double.parseDouble(ee1);
ff1 = ff.getText().toString();
double ff2 = Double.parseDouble(ff1);
if (ee.getText().toString().trim().length() == 0){
double sum = (aa2*bb2)/(cc2-dd2);
double sum2 = (sum * 10000) / ff2;
double total = Math.round((sum) * 10) / 10.0;
double total2 = Math.round((sum2) * 10) / 10.0;
answer.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer.setText(String.valueOf("Total Area Allocation = " + total + " ha"));
answer2.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer2.setText(String.valueOf("Set break " + total2 + " m"));
}
else if (cc.getText().toString().trim().length() == 0){
double sum = (aa2 * bb2)/ee2;
double sum2 = (sum * 10000) / ff2;
double total = Math.round((sum) * 10) / 10.0;
double total2 = Math.round((sum2) * 10) / 10.0;
answer.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer.setText(String.valueOf("Total Area Allocation = " + total + " ha"));
answer2.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer2.setText(String.valueOf("Set break " + total2 + " m"));
}
}
} catch (Exception e) {
answer.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer.setText("Enter values in input fields 2");
}
}
}
});

While it's not strictly on topic of why you're running into the exceptions, might I make some suggestions to help improve your code and hopefully reduce problems down the road.
Try to use more helpful variable names, it's hard to know what aa and bb actually are. Try to explain what they actually contain. numOfCows or what have you.
Move your logic into smaller functions. This will help you understand at a glance what the code does, and what other code it calls.
For example, create functions for handling each tab's calculation, and move that logic into there.
calculate.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View view) {
if (tabs.getCurrentTab() == 0) {
calculateFirstTab();
} else if (tabs.getCurrentTab() == 1) {
calculateSecondTab();
}
}
});
And lastly, try to reduce duplication. You have a lot of code that does the same thing, but you can make it a lot cleaner by creating small functions to help.
For example, here I have created a function called setAnswer that lets me pass in a TextView, and some text. This will let you set the background color is one place, and update the text. Then, creating another function called setAnswers that lets you pass in the totals, you can now set both answers just like that.
private void setAnswers( double total1, double total2 ){
setAnswer(answer, "Total Area Allocation = " + total1 + " ha");
setAnswer(answer2, "Set break " + total2 + " m");
}
private void setAnswer( TextView view, String text ) {
view.setBackgroundColor(Color.parseColor("#d6ffffff"));
view.setText(text);
}
There are definitely a lot of other ways to improve, but just some suggestions that may help you out.

Related

Google Map blink in Android TV when open for long time

I have android TV app which will run for long time .And I have google map inside that but after 20-24 hours google map starts blinking. Following link contains video of issue.
https://www.dropbox.com/s/vp8pbqc5z4zopbz/20180611_095004.mp4?dl=0
Edit
I can't share the whole source code, but I am using two fragments. One fragment contains map and another contains a listview of images. I call a webservice every 10 seconds and update listview images and bound map with locations I get in response of web service.
if ( map!=null) {
if (activity.ambDetailList.size() > 0) {
int i;
double dist, currentLat = 0.0, currentLng = 0.0;
ambOnlineList.clear();
String ETA, SPEED;
Marker marker;
for (i = 0; i < activity.ambDetailList.size(); i++) {
ambulanceDetail = activity.ambDetailList.get(i);
dist = Math.sqrt(Math.pow(ambulanceDetail.getCurrentLat() - ambulanceDetail.getDestLat(), 2) + Math.pow(ambulanceDetail.getCurrentLng() - ambulanceDetail.getDestLng(), 2));
double minute = ((dist * 100) / (ambulanceDetail.getSpeed() * 60 / 1000));
double speed = ambulanceDetail.getSpeed() * 60 * 60 / 1000;
Log.i("Minute", "----->>>>" + minute);
if (speed >= 0.00 && speed <= 1.00) {
ETA = activity.getResources().getString(R.string.text_infinity);
SPEED = activity.getResources().getString(R.string.text_infinity);
} else if (minute > 60) {
double hour = minute / 60;
int roundHour = (int) (minute / 60);
int min = (int) ((hour - roundHour) * 60);
ETA = roundHour + " hour " + min + " min";
SPEED = (int) (ambulanceDetail.getSpeed() * 60 * 60 / 1000) + " km/h ";
} else {
ETA = (int) (minute) + " min ";
SPEED = (int) (ambulanceDetail.getSpeed() * 60 * 60 / 1000) + " km/h ";
}
ambulanceDetail.setEta(ETA);
ambulanceDetail.setDisplayETA(ETA);
ambulanceDetail.setDisplaySpeed(SPEED);
if (markerList.get(ambulanceDetail.getAmbulanceId()) == null) {
MarkerOptions markerOptions = createMarker(ambulanceDetail);
marker = map.addMarker(markerOptions);
markerList.put(ambulanceDetail.getAmbulanceId(), marker);
markerArrayList.add(marker);
detailMap.put(marker, ambulanceDetail);
} else {
marker = markerList.get(ambulanceDetail.getAmbulanceId());
if (marker.isVisible()) {
Location location = new Location("");
location.setLatitude(ambulanceDetail.getCurrentLat());
location.setLongitude(ambulanceDetail.getCurrentLng());
marker.setIcon(BitmapDescriptorFactory.fromBitmap(updateMarkerIcon(ambulanceDetail)));
marker.setPosition(new LatLng(ambulanceDetail.getCurrentLat(), ambulanceDetail.getCurrentLng()));
}
}
ArrayList<Integer> listId = new ArrayList<>();
for (int m = 0; m < activity.ambDetailList.size(); m++) {
listId.add(activity.ambDetailList.get(m).getAmbulanceId());
}
for (int k = 0; k < markerArrayList.size(); k++) {
Marker m = markerArrayList.get(k);
if (!listId.contains(detailMap.get(m).getAmbulanceId())) {
markerArrayList.remove(m);
markerList.remove(detailMap.get(m).getAmbulanceId());
detailMap.remove(m);
m.remove();
}
}
}
if (markerList.size() == 1 && activity.ambDetailList.size() == 1) {
map.moveCamera(CameraUpdateFactory.newLatLngZoom(markerList.get(activity.ambDetailList.get(0).getAmbulanceId()).getPosition(), 16));
} else {
boundLatLang();
}
if (isFirstCall) {
map.setBuildingsEnabled(true);
isFirstCall = false;
}
} else {
if (markerArrayList.size() > 0) {
for (int i = 0; i < markerArrayList.size(); i++) {
Marker marker = markerArrayList.get(i);
marker.remove();
}
markerList.clear();
markerArrayList.clear();
}
map.clear();
if (detailMap.size() > 0)
detailMap.clear();
}
}
Anyway, you can restart application (or if that didn't helps - reboot device) before map starts blinking, for example after 15 hours of work (or e.g. 500 calls of web service):
...
Intent restartIntent = getBaseContext().getPackageManager()
.getLaunchIntentForPackage( getBaseContext().getPackageName() );
restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(restartIntent);
...

Saving and getting Latitude and Longitude for a mp4 file in android 7.0

Hi I have captured a video in android 7.0 and I got video file path. I need to store the Latitude and Longitude inside the video file i.e (Where the video was taken) like usually we do in images saving gps cordinates using Exif Interface. But using Exif Interface for mp4 file didn't work, instead I got an error:
java.lang.UnsupportedOperationException: ExifInterface only supports saving attributes on JPEG formats.
I thought of using the below code to save and fetch lat,long for video files also, but its not working.
This is the code I am using to save and get gps co-ordinates for images :
Saving Latitude and Longitude for a image:
public void setImageLatitudeLongitude(File imagePath, double imageLat, double imageLong) {
Log.e("Cordinates", "LAT : " + imageLat + "," + " LONG : " + imageLong);
try {
ExifInterface exif = new ExifInterface(imagePath.getPath());
int num1Lat = (int) Math.floor(imageLat);
int num2Lat = (int) Math.floor((imageLat - num1Lat) * 60);
double num3Lat = (imageLat - ((double) num1Lat + ((double) num2Lat / 60))) * 3600000;
int num1Lon = (int) Math.floor(imageLong);
int num2Lon = (int) Math.floor((imageLong - num1Lon) * 60);
double num3Lon = (imageLong - ((double) num1Lon + ((double) num2Lon / 60))) * 3600000;
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, num1Lat + "/1," + num2Lat + "/1," + num3Lat + "/1000");
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, num1Lon + "/1," + num2Lon + "/1," + num3Lon + "/1000");
Log.e("DMS LAT", num1Lat + "/1," + num2Lat + "/1," + num3Lat + "/1000");
Log.e("DMS LONG", num1Lon + "/1," + num2Lon + "/1," + num3Lon + "/1000");
if (imageLat > 0) {
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, "N");
} else {
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, "S");
}
if (imageLong > 0) {
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, "E");
} else {
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, "W");
}
exif.saveAttributes();
} catch (IOException e) {
e.printStackTrace();
}
}
Getting Latitude and Longitutde from an image:
public ArrayList getImageLatitudeLongitude(File imagePath) {
double imageLat = 0.0, imageLong = 0.0;
ArrayList<Double> arrayList = new ArrayList<Double>();
try {
ExifInterface exif = new ExifInterface(imagePath.getPath());
String latitude = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
String longitude = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
if (latitude != null && longitude != null) {
imageLat = convertToDegree(latitude);
imageLong = convertToDegree(longitude);
Log.e("Convert LAT", String.valueOf(convertToDegree(latitude)));
Log.e("Convert LONG", String.valueOf(convertToDegree(longitude)));
}
arrayList.add(imageLat);
arrayList.add(imageLong);
} catch (IOException e) {
arrayList.add(imageLat);
arrayList.add(imageLong);
e.printStackTrace();
}
return arrayList;
}
private Float convertToDegree(String stringDMS) {
Float result = null;
String[] DMS = stringDMS.split(",", 3);
String[] stringD = DMS[0].split("/", 2);
Double D0 = new Double(stringD[0]);
Double D1 = new Double(stringD[1]);
Double FloatD = D0 / D1;
String[] stringM = DMS[1].split("/", 2);
Double M0 = new Double(stringM[0]);
Double M1 = new Double(stringM[1]);
Double FloatM = M0 / M1;
String[] stringS = DMS[2].split("/", 2);
Double S0 = new Double(stringS[0]);
Double S1 = new Double(stringS[1]);
Double FloatS = S0 / S1;
result = new Float(FloatD + (FloatM / 60) + (FloatS / 3600));
return result;
}
And also how to get the latitude and longitude of the video file? Has anyone come across the same issue as I am facing, if so kindly suggest a solution for this problem. Thanks in advance!
ExifInterface only supports get attributes on image file.
You can use MediaMetadataRetriever class to get location data of video mp4 file. For example:
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource(videoPath);
String location = mediaMetadataRetriever
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION);

Unity3D - Get smooth speed and acceleration with GPS data

I'm using Unity3D and I created simple distance, speed and acceleration calculator using latitude and longitude of last position. I'm calculating last distance, speed and acceleration in each GPS update (approximately once per second). But sometimes (2-3 second interval) latitude and longitude values changes rapidly (in clear weather and no obstacles). That's why speed and acceleration values gets unreal results. For example, at stable 40 km/h speed, speed value becomes 60 km/h and returns to 40 km/h within 2-3 second. I'm here to ask how can I avoid this inaccurate and rapid GPS data changes?
I'm using Nexus 5 device
There is my code:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class Manager : MonoBehaviour
{
public Text longitude, latitude, lonAText, latAText, lonBText, latBText;
public Text result, overallResult, speedText, lastTimeText, timerText, accelerationText, speed0Text;
float lonA, lonB, latA, latB, overallDistance, lastDistance, timer, lastTime, speed, speed0, acceleration;
bool firstTime, allowTimer;
public AudioSource audio;
void Awake()
{
overallDistance = 0;
lastDistance = 0;
timer = 0;
lastTime = 0;
speed = 0;
speed0 = 0;
firstTime = true;
allowTimer = true;
}
IEnumerator Start()
{
// First, check if user has location service enabled
if (!Input.location.isEnabledByUser)
yield break;
// Start service before querying location
Input.location.Start(1, 1);
// Wait until service initializes
int maxWait = 20;
while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0)
{
yield return new WaitForSeconds(1);
maxWait--;
}
// Service didn't initialize in 20 seconds
if (maxWait < 1)
{
print("Timed out");
yield break;
}
// Connection has failed
if (Input.location.status == LocationServiceStatus.Failed)
{
print("Unable to determine device location");
yield break;
}
else
{
// Access granted and location value could be retrieved
print("Location: " + Input.location.lastData.latitude + " " + Input.location.lastData.longitude + " " + Input.location.lastData.altitude + " " + Input.location.lastData.horizontalAccuracy + " " + Input.location.lastData.timestamp);
longitude.text = Input.location.lastData.longitude.ToString();
latitude.text = Input.location.lastData.latitude.ToString();
lonA = Input.location.lastData.longitude;
latA = Input.location.lastData.latitude;
}
// Stop service if there is no need to query location updates continuously
//Input.location.Stop();
}
void Update()
{
longitude.text = Input.location.lastData.longitude.ToString();
latitude.text = Input.location.lastData.latitude.ToString();
timer += Time.deltaTime;
timerText.text = timer.ToString();
if (lonA != Input.location.lastData.longitude || latA != Input.location.lastData.latitude)
{
audio.Play();
CalculateDistances(lonA, latA, Input.location.lastData.longitude, Input.location.lastData.latitude); // last distance and overall distanceS
lonA = Input.location.lastData.longitude;
latA = Input.location.lastData.latitude;
lastTime = timer;
lastTimeText.text = lastTime.ToString();
timer = 0;
speed0 = speed;
speed0Text.text = speed0.ToString();
CalculateSpeed();
CalculateAcceleration();
}
}
public static float Radians(float x)
{
return x * Mathf.PI / 180;
}
public void CalculateDistances(float firstLon, float firstLat, float secondLon, float secondLat)
{
lonAText.text = firstLon.ToString();
latAText.text = firstLat.ToString();
lonBText.text = secondLon.ToString();
latBText.text = secondLat.ToString();
float dlon = Radians(secondLon - firstLon);
float dlat = Radians(secondLat - firstLat);
float distance = Mathf.Pow(Mathf.Sin(dlat / 2), 2) + Mathf.Cos(Radians(firstLat)) * Mathf.Cos(Radians(secondLat)) * Mathf.Pow(Mathf.Sin(dlon / 2), 2);
float c = 2 * Mathf.Atan2(Mathf.Sqrt(distance), Mathf.Sqrt(1 - distance));
lastDistance = 6371 * c * 1000;
result.text = lastDistance.ToString() + " meters";
overallDistance += lastDistance; // bu 1 anliq 6.000.000-dan boyuk qiymet ala biler
StartCoroutine(Overall());
}
IEnumerator Overall()
{
if (firstTime)
{
firstTime = false;
yield return new WaitForSeconds(2);
if (overallDistance > 6000000)
{
overallDistance = 0;
lastDistance = 0;
}
}
overallDistance += lastDistance;
overallResult.text = overallDistance.ToString() + " meters";
}
void CalculateSpeed()
{
speed = lastDistance / lastTime * 3.6f;
speedText.text = speed.ToString();
}
void CalculateAcceleration()
{
acceleration = (speed - speed0) / lastTime;
accelerationText.text = acceleration.ToString();
}
}

convert gregorian Date to hijri date is back wrong days

I want to convert from Gregorian to Hijri(Islamic) date and I use this class
the problem is islamic month's days is <29 , 30 , 29 , 30 else
but this class month's days is < 30, 29, 30, 29 else
any body can help fix this?
import java.util.Calendar;
/**
* Gregorian-Hijri Dates Converter
*
*
* This Code is used to convert Gregorian dates to Hijri Dates
*
*
*/
public class DateHigri {
static double gmod(double n,double m) {
return ((n % m) + m) % m;
}
static double[] kuwaiticalendar(boolean adjust) {
Calendar today = Calendar.getInstance();
int adj=0;
if(adjust){
adj=0;
}else{
adj=1;
}
if (adjust) {
int adjustmili = 1000 * 60 * 60 * 24 * adj;
long todaymili = today.getTimeInMillis() + adjustmili;
today.setTimeInMillis(todaymili);
}
double day = today.get(Calendar.DAY_OF_MONTH);
double month = today.get(Calendar.MONTH);
double year = today.get(Calendar.YEAR);
double m = month + 1;
double y = year;
if (m < 3) {
y -= 1;
m += 12;
}
double a = Math.floor(y / 100.);
double b = 2 - a + Math.floor(a / 4.);
if (y < 1583)
b = 0;
if (y == 1582) {
if (m > 10)
b = -10;
if (m == 10) {
b = 0;
if (day > 4)
b = -10;
}
}
double jd = Math.floor(365.25 * (y + 4716)) + Math.floor(30.6001 * (m + 1)) + day
+ b - 1524;
b = 0;
if (jd > 2299160) {
a = Math.floor((jd - 1867216.25) / 36524.25);
b = 1 + a - Math.floor(a / 4.);
}
double bb = jd + b + 1524;
double cc = Math.floor((bb - 122.1) / 365.25);
double dd = Math.floor(365.25 * cc);
double ee = Math.floor((bb - dd) / 30.6001);
day = (bb - dd) - Math.floor(30.6001 * ee);
month = ee - 1;
if (ee > 13) {
cc += 1;
month = ee - 13;
}
year = cc - 4716;
double wd = gmod(jd + 1, 7) + 1;
double iyear = 10631. / 30.;
double epochastro = 1948084;
double epochcivil = 1948085;
double shift1 = 8.01 / 60.;
double z = jd - epochastro;
double cyc = Math.floor(z / 10631.);
z = z - 10631 * cyc;
double j = Math.floor((z - shift1) / iyear);
double iy = 30 * cyc + j;
z = z - Math.floor(j * iyear + shift1);
double im = Math.floor((z + 28.5001) / 29.5);
if (im == 13)
im = 12;
double id = z - Math.floor(29.5001 * im - 29);
double[] myRes = new double[8];
myRes[0] = day; // calculated day (CE)
myRes[1] = month - 1; // calculated month (CE)
myRes[2] = year; // calculated year (CE)
myRes[3] = jd - 1; // julian day number
myRes[4] = wd - 1; // weekday number
myRes[5] = id; // islamic date
myRes[6] = im - 1; // islamic month
myRes[7] = iy; // islamic year
return myRes;
}
static String writeIslamicDate() {
String[] wdNames = {"Ahad", "Ithnin", "Thulatha", "Arbaa", "Khams",
"Jumuah", "Sabt"};
String[] iMonthNames = {"Muharram", "Safar", "Rabi'ul Awwal",
"Rabi'ul Akhir", "Jumadal Ula", "Jumadal Akhira", "Rajab",
"Sha'ban", "Ramadan", "Shawwal", "Dhul Qa'ada", "Dhul Hijja"};
// This Value is used to give the correct day +- 1 day
boolean dayTest=true;
double[] iDate = kuwaiticalendar(dayTest);
String outputIslamicDate = wdNames[(int) iDate[4]] + ", " + iDate[5] + " "
+ iMonthNames[(int) iDate[6]] + " " + iDate[7] + " AH";
return outputIslamicDate;
}
}

Prime Factorization in Android

I am developing a small Prime Number application for Android devices and am nearly done, however I would like some help with optimizing my factorization class.
I am still having one or two problems with some large numbers(Even Numbers) being factored within a reasonable amount of time. I won't be able to use the sieve of Eratosthenes for this particular project I think as I can only sieve up to 10 million without the app crashing on my physical device (Samsung Galaxy S4 Mini). So my work around algorithm is below. I am not sure if I can maybe make the Pollard Rho algorithm that I implemented any better.
Once I have established that the number being tested isn't prime or isn't a prime square, I quickly do trial division up to 10 000, after that if the number still isn't factored completely I use the Pollard Rho method to reduce it the rest of the way.
I want to be able to factor numbers in the range of 2 > 2^64.
This is an example of a number taking roughly 15 seconds 256332652145852
It's factorization is [2, 2, 1671053, 38348971].
Any help would be gladly appreciated.
try {
long num = Long.valueOf(input);
if(num == 1) {
return "1" + " = " + input;
} else if(num < 1) {
return "Cannot factor a number less than 1";
} else if(PrimeNumbers.isPrime(num) == true) {
return result = num + " is a Prime Number.";
} else if(isSquare(num) == true && PrimeNumbers.isPrime((long) Math.sqrt(num)) == true) {
return result = (int) Math.sqrt(num) + "<sup><small>" + 2 + "</small></sup>" + " = " + input;
} else {
factors(num, pFactors);
return result = exponentialForm(pFactors, num) + " = " + input;
}
} catch(NumberFormatException e) {
return result = "Unfortunately the number entered is too large";
}
}
public static void factors(long n, ArrayList<Long> arr) {
long number = trialDiv(n, arr);
if(number > 1) {
while(true) {
long divisor = pollard(number, 1);
if(PrimeNumbers.isPrime(divisor) == true) {
number /= divisor;
arr.add(divisor);
if(PrimeNumbers.isPrime(number) == true) {
arr.add(number);
break;
}
}
}
}
}
private static long trialDiv(long n, ArrayList<Long> arr) {
while(n % 2 == 0) {
n /= 2;
arr.add((long) 2);
}
for(long i = 3; i < 10000; i += 2) {
if(PrimeNumbers.isPrime(i) == true) {
while(n % i == 0) {
arr.add(i);
n /= i;
}
}
}
if(PrimeNumbers.isPrime(n) == true) {
arr.add(n);
return 1;
}
return n;
}
public static long pollard(long n, long c) {
long x = 2;
long y = 2;
long d = 1;
while (d == 1) {
x = g(x, n, c);
y = g(g(y, n, c), n, c);
d = gcd(Math.abs(y - x), n);
}
if (d == n) {
return pollard(n, c + 1);
} else {
return d;
}
}
static long g(long x, long n, long c) {
long g = (((x * x) + c) % n);
return g;
}
static long gcd(long a, long b) {
if (b == 0) {
return a;
} else {
return gcd(b, a % b);
}
}
Your pollard function is okay but not great. You are using Pollard's original algorithm, but it would be better to use Brent's variant. But that's probably not the source of your slow performance.
Your trial division function is slow. Checking each possible divisor for primality is very expensive, and not necessary. It doesn't matter if you divide by a composite; the division will always fail, but you don't waste the time checking primality. A better approach is wheel factorization.

Categories

Resources