rounding off values to 2 decimal places in java - java-7

I am using Java 7 and I just want to round off values to 2 decimal places, sample code is also given from various stackoverflow links :
Double d1= 4.37 , d2=0.694444444; //expected result after multiplication of numbers d1 and d2 is 3.04
DecimalFormat df = new DecimalFormat("#.#####");
String str = df.format(d1*d2);
d=(Double)df.parse(str);
System.out.println(d);//Prints 3.03472
df = new DecimalFormat("#.####");
str = df.format(d);
d= (Double)df.parse(str);
System.out.println(d);//Prints 3.0347
df = new DecimalFormat("#.###");
str = df.format(d);
d= (Double)df.parse(str);
System.out.println(d);//Prints 3.035
df = new DecimalFormat("#.##");
str = df.format(d);
d= (Double)df.parse(str);
System.out.println(d); //Prints my desired result 3.04
Is it not possible to possible to do this in 2 or 3 statements.
Regards
Kris

The problem is that the expected result 3.04 makes no sense, if you round to the closest value it should be 3.03. The result of 4.37*0.694444444 is 3.03472222028 and that is closer to 3.03 then to 3.04:
abs 3.03472222028 - 3.03 = 0.00472222028
abs 3.03472222028 - 3.04 = 0.00527777972
So actually all you need is
new DecimalFormat("#.##");
But as Klitos says, you would probably want to keep the real value as long as possible, and only round if you have to persist it to the database. Where you could use
String.format("%.2f", value)
Update 17/11
With the example you provided:
DecimalFormat df = new DecimalFormat("#.##");
String result = df.format(10.85*1/1.44);
The result is 7.53 (correct).
However, with your code, the result is 7.54, which is wrong.
That is because you round every digit sequentially and the errors accumulate, resulting in a rounding error, as can be seen in the example you provided.
So you really don't need to write your own rounding algorithm.You can just use the default from new DecimalFormat("#.##").

Related

How can i make my rounds() function in MATLAB, be very precised when handling around 400 values at a time?

I have made this function rounds() which rounds the values to the nearest multiple of 0.5, ie, rounds(2.685)=2.5 rounds(2.332)=2.5 rounds(2.7554)=3.0 rounds(2.245)=2.0 it works well in the way mentioned above, but while handling large number of values the precision drop. It does not give me the desired results. I have 30 functions, each of them computes 14 values which I pass in rounds() as a whole vector containing those 14 values. The results are like, for values for which it should return 3.0 such as rounds(2.7554) it only returns 2.5 and that affects my overall accuracy alot. Individually it works well for all values even 2.7554 returns 3.0 when i pass it to check its working. Can anyone tell me why this happens that while handling large number of values its performance decreases and also tell me the solution.
function [newVal] = rounds(x)
dist = mod(x, 0.5);
floorVal = x - dist;
if dist >=0.25
newVal = floorVal + 0.5;
else
newVal = floorVal;
end
end
The above is the rounds function and below i am showing how i have used it my functions.
if true
calc(1) = x+y;
calc(2) = x-y;
calc(3) = x*y+a;
.......
.......
.......
calc(14) = a+b*c+x;
calc = calc';
final_calc = rounds(calc);
end
Even in a single function the rounds function handles only 14 values at once still the result is not precised, while if i pass those same values individually it gives the correct output. Please solve this issue someone. Thanks in advance.
function [newVal] = rounds2(x)
newVal = round(x/0.5)*0.5;
end
This was something i was struggling for a long time but here I have now a perfect answer. This was happening because i was passing the vector expression dist >= 0.25 to if...end, incorrectly thinking that the if...end will be evaluated separately for each element of x(i). Hope that it helps some others too

float, round to 2 decimal places - Processing

I started learning processing since a short time ago and I came across a problem; When deviding 199.999 by 200 I want to outcome to be with 2 decimals (so the outcome should be 1 rounded of). Without formatting the outcome is 0.999995.
Code for formatting to String with 2 decimal:
float money = 199.999;
int munten = 200;
String calc1 = nf(money/munten,0,2);
println(calc1);
float calc2 = float(calc1);
println(calc2);
Prints:
1,0
NaN
I think float() wont work cause there is a comma in the String instead of a dot, I'm not sure tough. But how can I round a number to 2 decimal and still let it be a float?
Thanks for taking your time to read this,
When I run your example on Processing 3.3.6 / macOS 10.12 (US), I get "1.00" and "1.0". This could be due to your number formatting settings creating output strings that are then not read correctly by nf().
float money;
int munten;
String s;
float f;
money = 199.999;
munten = 200;
s = nf(money/munten, 0, 2);
println(s); // "1.00" -- or "1,0" etc. in different os language locales
f = float(s);
println(f); // "1.0" -- or NaN error if above is not 1.0 format
f = money/munten;
println(f); // 0.999995
s = nf(f, 0, 2);
println(s); // 1.00 -- or local format
You can see what should be happening more clearly in the second bit of code -- don't try to convert into a String and then back out again; don't store numbers in Strings. Instead, keep everything in numeric variables up until the moment you need to display.
Also keep in mind that nf() isn't really for rounding precision, although it is often used that way:
nf() is used to add zeros to the left and/or right of a number. This is typically for aligning a list of numbers. To remove digits from a floating-point number, use the int(), ceil(), floor(), or round() functions. https://processing.org/reference/nf_.html
If you need to work around your locale, you can use Java String formatting in Processing to do so:
float fval = 199.999/200;
println(fval); // 0.999995
String s = String.format(java.util.Locale.US,"%.2f", fval);
println(s); // 1.00
See https://stackoverflow.com/a/5383201/7207622 for more discussion of the Java approach.

Fast string splitting in MATLAB

I've been using MATLAB to read through a bunch of output files and have noticed that it was reading the files fairly slowly in comparison to a reader that I wrote in Python for the same files (on the order of 120s for MATLAB, 4s for Python on the same set). The files have a combination of letters and numbers, where the numbers I actually want each have a unique string on the same line, but there is no real pattern to the rest of the file. Is there a faster way to read in non-uniformly formatted text files in MATLAB?
I tried using the code profiler in MATLAB to see what takes the most time, and it seemed to be the strfind and strsplit functions. Deeper down, the strfun\private\strescape seems to be the culprit which takes up around 50% of the time, which is called by strsplit function.
I am currently using a combination of strfind and strsplit in order to search through a file for 5 specific strings, then convert the string after it into a double.
lots of text before this
#### unique identifying text here
lots of text before this
sometext X = #####
Y = #####
Z = #####
more text = ######
I am iterating through the file with approximately the following code, repeated for each number that is being found.
fid=fopen(filename)
tline=fgets(fid)
while ischar(tline)
if ~isempty(strfind(tline('X =')))
tempstring=strsplit(tline(13:length(tline)),' ');
result=str2double(char(tempstring(2)));
end
tline=fgets(fid);
end
I'm guessing this will be a bit faster, but maybe not by much.
s = fileread('texto');
[X,s] = strtok(strsplit(s, "X = "){2}); X = str2num(X);
[Y,s] = strtok(strsplit(s, "Y = "){2}); Y = str2num(Y);
[Z,s] = strtok(strsplit(s, "Z = "){2}); Z = str2num(Z);
Obviously this is highly specific to your text example. You haven't given me any more info on how the variables might change etc so presumably you'll have to implement try/catch blocks if files are not consistent etc.
PS. This is octave syntax which allows chaining operations. For matlab, split them into separate operations as appropriate.
EDIT: ach, nevermind, here's the matlab compatible one too. :)
s = fileread('texto');
C = strsplit(s, 'X = '); [X,s] = strtok(C{2}); X = str2num(X);
C = strsplit(s, 'Y = '); [Y,s] = strtok(C{2}); Y = str2num(Y);
C = strsplit(s, 'Z = '); [Z,s] = strtok(C{2}); Z = str2num(Z);

Why does the result being so different

I was new to Matlab,and this time I want to create a function for its image process.
Firstly, I download a picture from the Internet.Then I named it "map.jpg",and copy to my workspace.latter,I create a M_files and type the code into the files.
for example:
function y=mean_data(gray)
s=size(gray);
sum=0;
for i=1:s(1)
for j=1:s(2)
sum=sum+gray(i,j);
end
end
y=sum/(s(1)*s(2));
Finally,the difference happenend:
if I call the function in this way:
I=imread('map.jpg');
J=rgb2gray(I);
mean=mean_data(double(J))
the result will be OK.
However if I call in this way:
I=imread('map.jpg');
J=rgb2gray(I);
mean=mean_data(J)
the result will be zero.
So why does the result being so different?And thank you for helping me!!!
This is becuase the default output format of the data read by imread
is uint8 that is - 8 bit per R/G/B. With 8 bit you can't get any integer
higher than 255. Take a look:
>> uint8(250) + uint8(5)
ans =
255
>> uint8(250) + uint8(6)
ans =
255
So then, during division in your function this thing happens:
>> uint8(255) / 12345
ans =
0
However, when you use double() you change the representation of
your data to 64 bit floating point - a lot more room for representing big
numbers.
Instead of using your loop function you can use matlab's mean
function - it works well with uint8 format:
>> mean(uint8([255, 231]))
ans =
243
So you can use:
mean_dat = mean(mean(J));
% it is also not a good idea to name a variable 'mean'
% if you are going to use the mean function so I renamed
% your variable to mean_dat

Sum of values between start and end date in MATLAB

If, in MATLAB, I have a set of start and end dates that represent a contiguous period of time, how would I take a separate daily time series and accumulate any values from said time series over each start/end pair?
Is this something that can be done with accumarray()? It wasn't clear to me whether it would be efficient to construct the vector that groups each element of the time series by start/end pair.
Inputs
Start Date End Date
01/01/12 01/31/12
02/01/12 02/28/12
...
Date Value
01/01/12 23
01/02/12 87
01/03/12 5
01/04/12 12
...
02/01/12 4
Output
Start Date End Date Value
01/01/12 01/31/12 127
02/01/12 02/28/12 4
...
For consecutive periods of time, the following approach might work. Note that the strings containing dates are cellstrings and, for consecutive data, only the first column of your start date /end date matrix is necesssary.
Furthermore, note that I separated your time series data into two variables for the sake of clarity.
dateBins = {...
'01/01/12';
'02/01/12';
'03/01/12';
'04/01/12'};
dates = {
'01/01/12'
'01/02/12'
'01/03/12'
'01/04/12'
'02/01/12' };
values = [
23
87
5
12
4];
With these variables, the following code
[thrash, idx] = histc(datenum(dates), datenum(dateBins))
accumVal = accumarray(idx, values);
result = zeros(length(dateBins), 1);
result(1:length(accumVal),1) = accumVal;
will result in:
result =
127
4
0
0
Assuming you have already got two vectors with the start dates and end dates in a format that you can use to compare and you just want to count how many occurrences there are in each cateogory, then it is quite straightforward:
% Your data
Dates = 25*rand(10,1);
StartDate = [1 10 20];
EndDate = [9 19 29];
% The Calculation
Result = zeros(size(StartDate)); %Initialization
for d = 1:length(startdate)
idx = dates >= StartDate & dates <= EndDate;
Result(d) = sum(idx);
end
Note that this will require that you store your dates in a comparable format.
I would iterate over each pair of start/end dates. Then pick out the index start/stop pairs and sum them. If you use datestrs, you can make the following less brittle, while allowing for more flexibility in how you represent times that cross years, etc.
start_date = {'01/01/12'};
end_date={'01/31/12'};
datevec={'01/01/12','01/02/12','01/03/12','01/31/12'};
values=[23,87,5,12];
for i=1:numel(start_date)
is = find(ismember(datevec,start_date{i})==1);
ie = find(ismember(datevec,end_date{i})==1);
sum(values(is:ie))
end

Resources