t=find(str.tubetime >= str.time,1);
assume tubetime is a matrix of 1 x 1001 elements
assume time is a double =0.0012
From what I understand of the code is it finds the first value of the tubetime matrix which is
of equal or greater value returning the index of where this value is found in tubetime.
If I am correct, why am I getting an index value of 244. When the value of 0.0012 is contained at index points starting at 231 through to the index point 250.
Edit:
I have just double checked my variables are accurate, as I am currently in debug mode, and reading it back from the system. Thank you for your input, do you have any idea what could be wrong with it?
Here is a screenshot showing the values
When you view the values in printscreen it is probably cutting off after the 4th decimal place. See my comment above on your original post.
Your description of FIND is correct, but one of your variables is not as you described it. e.g.,
t=find([1 1 2 3 4 5 6] >= 3,1)
returns 4, as it should.
You have specifically asked that it should return only one element in your syntax
time = zeros(1,1001);
time(231:250) = 0.0012 % setting an array where indices 231 - 250 are 0.0012 else is zero
find(time>=0.0012)
% gives all indices
find(time>=0.0012,1)
%returns 231 only
find(time>=0.0012,2)
%returns 231,232
PLUS check that the values are not shown in short format, that is they are 0.001199 but shown as 0.0012.
Related
If A = 01110011, B = 10010100, how would I add these?
I did this:
i.e: 01110011 + 10010100 = 100000111
Though, isn't it essentially 115 + (-108) = 7, whereas, I'm getting -249
Edit: I see that removing the highest order bit (overflow) I get 7 which is what I'm looking for but I'm not getting why you wouldn't have the extra bit.
Edit**: Ok, I figured it out. There was no overflow as I had assumed there was because 7 is within [-128, 127] (8-bits). Instead, like Omar hinted at I was supposed to drop the "extra" 1 from addition.
Your calculation is correct and the result is correct.
You stated that the second number is -108, so both your numbers are interpreted as signed 8-bit values. Thus, you should also interpret your result as an 8-bit signed value, this is why the 9th bit must be dropped, and so the result is 7 (00000111).
On a real hardware, like an 8-bit CPU for example, as all the registers are 8-bit wide, you are only be able to store the lowest 8-bit of the result, which here is 7 (00000111).
In some cases, the 9th bit may also be put inside a carry/overflow flag so it's not completely "dropped".
Hi after calling this code (Octave) I get an answer with 7 digits of precision, I need only 6. It is worth mentioning that on different data-set the output is normal(with 6 digits);
output_precision(6);
Prev
output:
Prev =
0.1855318
0.2181108
0.1796457
I know this is a little late but I wanted to add an answer for anyone with the same question in the future.
According to the function reference for output_precision(), the argument passed to the function (in this case, 6) specifies the minimum number of significant figures, which only guarantees that future numeric output won't have less than that number of significant figures.
From what I've seen, if you use output_precision(new_val) before displaying an array (e.g., Prev in the question), then octave will round the element with the least digits before the decimal place to have new_val significant figures and then all other elements will be rounded to have the same number of digits after the decimal place as that initial rounded result. If you use a statement to output a single value instead of an array, then the output is just rounded to new_val significant figures. However, I don't know if this behavior is guaranteed .
Here's a short example of what I mean:
% array defined with values having 5 digits after decimal
F = [401.51670 313.70753 -88.55225 188.50067 280.21988 354.51821 54.51821 350];
output_precision(4)
F
output_precision(6)
F
Output:
F =
401.52 313.71 -88.55 188.50 280.22 354.52 54.52 350.00
F =
401.5167 313.7075 -88.5523 188.5007 280.2199 354.5182 54.5182 350.0000
It can be a little quirky if you try to round the values too much. When I used output_precision(3) and then output F, the numbers were actually rounded as if my system's default precision, 5, was still active. However, when I used elements with only 2 or 3 digits after the decimal to define another array, it displayed as expected with output_precision(3).
Check out Octave Forge if you ever need docs for octave features. It's not perfect but it's something. Hope this was helpful.
This is my first time trying to complete work in Octave. I have attempted to complete "for loops" to get the mean of each and then subtract this to centre the results in the 25 samples of the 5 items. I get the right figures, however I also get an out of bounds error (indicated below). Can anyone help me please?
error: TrialPartB: A(I,J): row index out of bounds; value 6 out of bound 5
You have populated your G_all structure with only 5 data members, but then, when you calculate the mean, you loop i=1:25. There are only 5 members, so when it gets to member 6, it fails with the 'row index out of bounds' error.
You need to limit the for loop to be just the size of the data, perhaps using rows(G_all) instead of 25 as the limit of the loop.
As rolfl already explained you are trying to access row 1..25 but G_all only has 5 rows.
But apart that problem you shouldn't calculate mean in a for loop but use the function "mean" instead.
a=[4 1 6];
mean(a)
ans = 3.6667
If you want to remove the mean from an vector just use "detrend":
detrend(a, 0)
ans =
0.33333 -2.66667 2.33333
SO,
The problem
I have an issue with rows multiplication. In SQL, there is a SUM() function which calculates sum for some field for set of rows. I want to get multiplication, i.e. for table
+------+
| data |
+------+
| 2 |
| -1 |
| 3 |
+------+
that will be 2*(-1)*3 = -6 as a result. I'm using DOUBLE data type for storing my data values.
My approach
From school math it is known that log(A x B) = log(A) + log(B) - so that could be used to created desired expression like:
SELECT
IF(COUNT(IF(SIGN(`col`)=0,1,NULL)),0,
IF(COUNT(IF(SIGN(`col`)<0,1,NULL))%2,-1,1)
*
EXP(SUM(LN(ABS(`col`))))) as product
FROM `test`;
-here you see weakness of this method - since log(X) is undefined when X<=0 - I need to count negative signs before calculating whole expression. Sample data and query for this is given in this fiddle.
Another weakness is that we need to find if there is 0 among column values (Since it is a sample, in real situation I'm going to select product for some subset of table rows with some condition(s) - i.e. I can not simply remove 0-s from my table, because result zero product is a valid and expected result for some rows subsets)
Specifics
And now, finally, my question main part: how to handle situation when we have expression like: X*Y*Z and here X < MAXF, Y<MAXF, but X*Y>MAXF and X*Y*Z<MAXF - so we have possible data type overflow (here MAXF is limit for double MySQL data type). The sample is here. Query above works well, but can I always be sure that it will handle that properly? I.e. may be there is another case with overflow issue when some sub-products causing overflow, but entire product is ok (without overflow).
Or may be there is another way to find rows product? Also, in table there possibly be millions of records (-1.1<X<=1.1 mainly, but probably with values such as 100 or 1000 - i.e. high enough to overflow DOUBLE if multiplied with certain quantity if we have an issue that I've described above) - may be calculating via log will be slow?
I guess this would work...
SELECT IF(MOD(COUNT(data < 0),2)=1
, EXP(SUM(LOG(data)))*-1
, EXP(SUM(LOG(data))))
x
FROM my_table;
If you need this type of calculations often, I suggest you store the signs and the logarithms in separate columns.
The signs can be stored as 1 (for positives), -1 (for negatives) and 0 (for zero.)
The logarithm can be assigned for zero as 0 (or any other value) but it should not be used in calculations.
Then the calculation would be:
SELECT
CASE WHEN EXISTS (SELECT 1 FROM test WHERE <condition> AND datasign = 0)
THEN 0
ELSE (SELECT 1-2*(SUM(datasign=-1)%2) FROM test WHERE <condition>)
END AS resultsign,
CASE WHEN EXISTS (SELECT 1 FROM test WHERE <condition> AND datasign = 0)
THEN -1 -- undefined log for result 0
ELSE (SELECT SUM(datalog) FROM test WHERE <condition> AND datasign <> 0)
END AS resultlog
;
This way, you have no overflow problems. You can check the resultlog if it exceeds some limits or just try to calculate resultdata = resultsign * EXP(resultlog) and see if an error is thrown.
This question is a remarkable one in the sea of low quality ones. Thank you, even reading it was a pleasure.
Precision
The exp(log(a)+log(b)) idea is a good one in itself. However, after reading "What Every Computer Scientist Should Know About Floating-Point Arithmetic", make sure you use DECIMAL or NUMERIC data types to be sure you are using Precision Math, or else your values will be surprisingly inaccurate. For a couple of million rows, errors can add up very quickly! DECIMAL (as per the MySQL doc) has a maximum of 65 digits precision, while for example 64bit IEEE754 floating point values have only up to 16 digits (log10(2^52) = 15.65) precision!
Overflow
As per the relevant part of the MySQL doc:
Integer overflow results in silent wraparound.
DECIMAL overflow results in a truncated result and a warning.
Floating-point overflow produces a NULL result. Overflow for some operations can result in +INF, -INF, or NaN.
So you can detect floating point overflow if it would ever happen.
Sadly, if a series of operations would result in a correct value, fitting into the data type used, but at least one subresult in the process of calculations would not, then you won't get the correct value at the end.
Performance
Premature optimization is the root of all evil. Try it, and if it is slow, take the appropriate actions. Doing this might not be lightning quick, but still might be quicker than getting all the results, and doing it on the application server. Only measurements can decide which gets to be quicker...
I am calculating percentages. One example is coming down to 38589/38400
So the percentage is 100*(38589/38400) which equals something like 100.4921875, but the result shows up as 100.
How can I get it to be displayed with x number of decimals?
Similarly, will the same work if i'd like 2 to be displayed as 2.000000?
Thanks!
You can cast it to a specific data type, which preserves the data type as well as rounding to a certain precision
select cast(100*(38589/38400) as decimal(10,4))
FYI
select 100*(38589/38400)
# returns 100.4922, not 100 for me
select cast(2 as decimal(20,6))
# output : 2.000000
With regards to your number formatting have you looked at the format function:
mysql> SELECT FORMAT(12332.123456, 4);
-> '12,332.1235'
mysql> SELECT FORMAT(12332.1,4);
-> '12,332.1000'
mysql> SELECT FORMAT(12332.2,0);
-> '12,332'
so to get 2.000000 from 2 do:
SELECT FORMAT(2,6);
Also, according to mySQL's documentation regarding division:
In division performed with /, the
scale of the result when using two
exact-value operands is the scale of
the first operand plus the value of
the div_precision_increment system
variable (which is 4 by default). For
example, the result of the expression
5.05 / 0.014 has a scale of six decimal places (360.714286).
These rules are applied for each
operation, such that nested
calculations imply the precision of
each component. Hence, (14620 /
9432456) / (24250 / 9432456), resolves
first to (0.0014) / (0.0026), with the
final result having 8 decimal places
(0.60288653).
This would lead me to agree with #Cyberwiki regarding the result you would see from your division.
You need to convert one of the types to floating point:
SELECT 100.0 * ((338589 * 1.0)/38400) ...
With regards to the reason why the result shows 100 instead of 100.4921875 is maybe related to the type of the corresponding column assuming that you store the result in a table column. Make sure that the type of that column is Double.
If you'd like 2 to be displayed as 2.000000, just multiply it by 1.0 as follows:
(select (100*(38589/38400*1.0))
and the output will show: 100.49219