As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
I was going through a programming class and was asked this tricky question which was left unanswered till the end of the class.
Question:
How can I multiply any input(Float,int etc) by 7,
without using the * operator
in TWO steps.
If anyone can give me the answer for this question with the explanation , that would be very helpful.
With TWO STEPS I mean suppose you are running a loop (i=0;i<7;i++) in
that case number of steps will be >2, also TYPE CONVERSION,
DIVISION,ADDITION etc ( Counts for steps ).
Assuming float x or double x is defined in the scope. Then I see the following possibilities to multiply it by 7 without using the * operator:
In C++, you can use the standard functors (first step: create functor, second step: call functor):
x = std::multiplies<float>()(x, 7.0f); // if x is a float
x = std::multiplies<double>()(x, 7.0); // if x is a double
Or only use division (Since the compiler already evaluates 1.0 / 7.0, this is only one step):
x = x / (1.0f / 7.0f); // if x is a float
x = x / (1.0 / 7.0); // if x is a double
Or use the *= operator (technically, it's not the * operator, but it's only one single step):
x *= 7.0f; // if x is a float
x *= 7.0; // if x is a double
Or use addition in the logarithmic scale (this is not to be taken very serious, as well as this requires more than two "steps"):
x = exp(log(x) + log(7.0));
Another option is to use an assembly instruction, but I don't want to write that now, since it's overly complicated.
If x is an integer, bit shifting is another option, but not recommended:
x = (x << 3) - x; // (x * 8) - x
You could simply use division by a seventh:
x / (1.0 / 7)
Whether this counts as "two steps" is entirely up to your definition.
add it
//initialise s as the number to be multiplied
sum=0
for(i=0;i<7;i++)
sum+=s
In C, the following hack should work for floats stored in IEEE single precision floating point format:
#include <stdint.h>
float mul7 (float x) {
union {
float f;
uint32_t i;
} u;
u.f = x;
u.i += (3 << 23); /* increment exponent by 3 <=> multiply by 8 */
return u.f - x; /* 8*x - x == 7*x */
}
That's two steps (one integer addition, one float subtraction), sort of, depending on what you count as a step. Given that C++ is more or less backwards-compatible with C, I believe a similar trick should be possible there too.
Note, however, that this hack generally won't give correct results for subnormal, infinite or NaN inputs, nor for inputs so large in magnitude that multiplying them by 8 would overflow.
Adjusting the code to use doubles instead of float is left as an exercise for the reader. (Hint: the magic number is 52.)
You may also do the following for integers:
( x<< 3) - x
// String num = "10";
// int num = 10;
float num = 10;
BigDecimal bigD = new BigDecimal(num);
BigDecimal seven = new BigDecimal(7);
System.out.println(seven.multiply(bigD));
You could use the BigDecimal & its multiply method. Works for pretty much everything.
Define "two steps"...
float result = 0.0f;
float input = 3.14f;
int times = 7;
// steps
while (times--)
result += input;
Edit: dividing by (1 / 7) won't work with int type. Also in some languages for it to work with float type, you'd have to mark them as floats:
result = input / (1.0f / 7.0f);
Add 7 by x times.
for(int i=0; i<10; i++)
result = result+7;
Related
This question already has answers here:
The accuracy of a double in general programming and Java
(2 answers)
Division of integers in Java [duplicate]
(7 answers)
Closed 6 years ago.
I have the following two calculation using Math.round(...):
double x = 0.57145732;
x = x * 100;
x = Math.round(x * 10);
x = x / 10;
If I now print the value of x it will show me: 57.1.
double x = 0.57145732;
x = (Math.round((x * 100) * 10)) / 10;
// x = (Math.round(x * 1000)) / 10; //Also gives me 57.0.
If I now print the value of x it will show me: 57.0.
Why is there this difference in the outcome?
The Math.round() method returns an integer (of type long - as pointed out by Ole V.V). It's usually thought to return a float or double which gives rise to confusions as these.
In the second calculation,
Math.round((x * 100) * 10)
returns 571. Now, this value and 10 both are integers (571 is long, 10 is int). So when the calculation takes the form
x = 571 / 10
where x is double, 571/10 returns 57 instead of 57.1 since it is int. Then, 57 is converted to double and it becomes 57.0
If you do
x = (double)Math.round((x * 100) * 10) / 10.0;
its value becomes 57.1.
Edit: There are two versions of the Math.round() function. The one you used accepts a double (since x is double) and returns long. In your case, implicit type casting spares you the trouble of considering the precise little details.
The reason of the difference is that in the second formula you're making a division of two integer. in order to have the same result you have to add a cast to double:
double x = 0.57145732;
x = (double)(Math.round((x * 100) * 10)) / 10;
The difference is between
x = Math.round(571.45732) / 10;
and
x = Math.round(571.45732);
x = x / 10;
Since round(double) returns a long, in the first case you divide a long by an int, giving the long 57. Converting back to double leads to 57.0. The second case is equivalent to
x = ((double)Math.round(571.45732)) / 10;
where a double is divided by an int, resulting in 57.1.
This because Math.round() returns an int. If you do this step-by-step (as in the first example), you assign the result of Math.round() to a float value. The following calculation uses then a float division.
In the second example, you let the JVM decide which types to use (and it uses an integer division as the intermediate step). This is why the precision gets lost.
How can I multiply and divide without using arithmetic operators? I read similar question here but i still have problem to multiply and divide.
Also, how can square root be calculated without using math functions?
if you have addition and negation, as in the highest voted answer to the post you gave, you can use looped additions and subtractions to implement multiplication and division.
As for the square root, just implement Newton's Iteration on the basis of the operations from step 1.
Using bitwise operators one example I found is here:
http://geeki.wordpress.com/2007/12/12/adding-two-numbers-with-bitwise-and-shift-operators/
Addition can be translated to multiplicity and division. For sqrt you could use Taylor series.
http://en.wikipedia.org/wiki/Taylor_series
Fast square root function(even faster than the library function!):
EDIT: not true, actually slower because of recent hardware improvements. This is however the code used in Quake II.
double fsqrt (double y)
{
double x, z, tempf;
unsigned long *tfptr = ((unsigned long *)&tempf) + 1;
tempf = y;
*tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */
x = tempf;
z = y*0.5; /* hoist out the “/2” */
x = (1.5*x) - (x*x)*(x*z); /* iteration formula */
x = (1.5*x) – (x*x)*(x*z);
// x = (1.5*x) – (x*x)*(x*z); /* not necessary in games */
return x*y;
}
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Java Integer Division, How do you produce a double?
double wang = 3 / 2;
Log.v("TEST", "Wang: " + Double.toString(wang));
Logcat output...
07-04 09:01:03.908: VERBOSE/TEST(28432): Wang: 1.0
I'm sure there's an obvious answer to this and probably I'm just tired from coding all night but this has me stumped.
In many languages, Java being one of them, the way you write a number in an expression decides what type it gets. In Java, a few of the common number types behave like this1:
// In these cases the specs are obviously redundant, since all values will be
// cast correctly anyway, but it was the easiest way to show how to get to the
// different data types :P
int i = 1;
long l = 1L;
float f = 1.0f; // I believe the f and d for float and double are optional, but
double d = 1.0d; // I wouldn't bet on what the default is if they're omitted...
Thus, when you declare 3 / 2, you're really saying (the integer 3) / (the integer 2). Java performs the division, and finds the result to be 1 (i.e. the integer 1...) since that's the result of dividing 3 and 2 as integers. Finally, the integer 1 is cast to the double 1.0d which is stored in your variable.
To work around this, you should (as many others have suggested) instead calculate the quotient of
(the double 3) / (the double 2)
or, in Java syntax,
double wang = 3.0 / 2.0;
1 Source: The Java Tutorial from Oracle
Integer division of 3 by 2 is equal to 1 with residue of 1. Casting to double gives 1.0
3 and 2 are integer constants and therefore 3 / 2 is an integer division which results in 1 which is then cast into a double. You want 3.0 / 2.0
Try: double wang = 3.0 / 2.0;
That's the expected behaviour. "3" and "2" are both int values, and when you perform 3 / 2 the result will also be an int value which gets rounded down to 1. if you cast both to double before you perform the division then you'll get the result that you expect:
double wang = (double)3 / (double)2;
I am working on an exercise in Java. I am supposed to use / and % to extract digits from a number. The number would be something like 1349.9431. The output would be something like:
1349.9431
1349.943
1349.94
1349.9
I know this is a strange way to do but the lab exercise requires it.
Let's think about what you know. Let say you have the number 12345. What's the result of dividing 12345 by 10? What's the result of taking 12345 mod 10?
Now think about 0.12345. What's the result of multiplying that by 10? What's the result of that mod 10?
The key is in those answers.
if x is your number you should be able to do something like x - x%0.1 to get the 1349.9, then x - x%.0.01 to get 1349.94 and so on. I'm not sure though, doing mod on floats is kind of unusual to begin with, but I think it should work that way.
x - x%10 would definetly get you 1340 and x - x%100 = 1300 for sure.
Well the work will be done in background anyway, so why even bother, just print it.
float dv = 1349.9431f;
System.out.printf("%8.3f %8.2f %8.1f", dv, dv, dv);
Alternatively this could be archived with:
float dv = 1349.9431f;
System.out.println(String.format("%8.3f %8.2f %8.1f", dv, dv, dv));
This is a homework question so doing something the way you would actually do in the real world (i.e. using the format method of String as Margus did) isn't allowed. I can see three constraints on any answer given what is contained in your question (if these aren't actually constraints you need to reword your question!)
Must accept a float as an input (and, if possible, use floats exclusively)
Must use the remainder (%) and division (/) operator
Input float must be able to have four digits before and after the decimal point and still give the correct answer.
Constraint 1. is a total pain because you're going to hit your head on floating point precision quite easily if you have to use a number with four digits before and after the decimal point.
float inputNumber = 1234.5678f;
System.out.println(inputNumber % 0.1);
prints "0.06774902343743147"
casting the input float to a double casuses more headaches:
float one = 1234.5678f;
double two = (double) one;
prints "1234.5677490234375" (note: rounding off the answer will get you 1234.5677, which != 1234.5678)
To be honest, this had me really stumped, I spent way too much time trying to figure out how to get around the precision issue. I couldn't find a way to make this program work for 1234.5678f, but it does work for the asker's value of 1349.9431f.
float input = 1349.9431f;
float inputCopy = input;
int numberOfDecimalPoints = 0;
while(inputCopy != (int) inputCopy)
{
inputCopy = inputCopy * 10;
numberOfDecimalPoints++;
}
double inputDouble = (double) input;
double test = inputDouble * Math.pow(10, numberOfDecimalPoints);
long inputLong = Math.round(test);
System.out.println(input);
for(int divisor = 10; divisor < Math.pow(10, numberOfDecimalPoints); divisor = divisor * 10)
{
long printMe = inputLong - (inputLong % divisor);
System.out.println(printMe / Math.pow(10, numberOfDecimalPoints));
}
Of my three constraints, I've satisfied 1 (kind of), 2 but not 3 as it is highly value-dependent.
I'm very interested to see what other SO people can come up with. If the asker has parsed the instructions correctly, it's a very poor exercise, IMO.
Since the trigonometric functions in java.lang.Math are quite slow: is there a library that does a quick and good approximation? It seems possible to do a calculation several times faster without losing much precision. (On my machine a multiplication takes 1.5ns, and java.lang.Math.sin 46ns to 116ns). Unfortunately there is not yet a way to use the hardware functions.
UPDATE: The functions should be accurate enough, say, for GPS calculations. That means you would need at least 7 decimal digits accuracy, which rules out simple lookup tables. And it should be much faster than java.lang.Math.sin on your basic x86 system. Otherwise there would be no point in it.
For values over pi/4 Java does some expensive computations in addition to the hardware functions. It does so for a good reason, but sometimes you care more about the speed than for last bit accuracy.
Computer Approximations by Hart. Tabulates Chebyshev-economized approximate formulas for a bunch of functions at different precisions.
Edit: Getting my copy off the shelf, it turned out to be a different book that just sounds very similar. Here's a sin function using its tables. (Tested in C since that's handier for me.) I don't know if this will be faster than the Java built-in, but it's guaranteed to be less accurate, at least. :) You may need to range-reduce the argument first; see John Cook's suggestions. The book also has arcsin and arctan.
#include <math.h>
#include <stdio.h>
// Return an approx to sin(pi/2 * x) where -1 <= x <= 1.
// In that range it has a max absolute error of 5e-9
// according to Hastings, Approximations For Digital Computers.
static double xsin (double x) {
double x2 = x * x;
return ((((.00015148419 * x2
- .00467376557) * x2
+ .07968967928) * x2
- .64596371106) * x2
+ 1.57079631847) * x;
}
int main () {
double pi = 4 * atan (1);
printf ("%.10f\n", xsin (0.77));
printf ("%.10f\n", sin (0.77 * (pi/2)));
return 0;
}
Here is a collection of low-level tricks for quickly approximating trig functions. There is example code in C which I find hard to follow, but the techniques are just as easily implemented in Java.
Here's my equivalent implementation of invsqrt and atan2 in Java.
I could have done something similar for the other trig functions, but I have not found it necessary as profiling showed that only sqrt and atan/atan2 were major bottlenecks.
public class FastTrig
{
/** Fast approximation of 1.0 / sqrt(x).
* See http://www.beyond3d.com/content/articles/8/
* #param x Positive value to estimate inverse of square root of
* #return Approximately 1.0 / sqrt(x)
**/
public static double
invSqrt(double x)
{
double xhalf = 0.5 * x;
long i = Double.doubleToRawLongBits(x);
i = 0x5FE6EB50C7B537AAL - (i>>1);
x = Double.longBitsToDouble(i);
x = x * (1.5 - xhalf*x*x);
return x;
}
/** Approximation of arctangent.
* Slightly faster and substantially less accurate than
* {#link Math#atan2(double, double)}.
**/
public static double fast_atan2(double y, double x)
{
double d2 = x*x + y*y;
// Bail out if d2 is NaN, zero or subnormal
if (Double.isNaN(d2) ||
(Double.doubleToRawLongBits(d2) < 0x10000000000000L))
{
return Double.NaN;
}
// Normalise such that 0.0 <= y <= x
boolean negY = y < 0.0;
if (negY) {y = -y;}
boolean negX = x < 0.0;
if (negX) {x = -x;}
boolean steep = y > x;
if (steep)
{
double t = x;
x = y;
y = t;
}
// Scale to unit circle (0.0 <= y <= x <= 1.0)
double rinv = invSqrt(d2); // rinv ≅ 1.0 / hypot(x, y)
x *= rinv; // x ≅ cos θ
y *= rinv; // y ≅ sin θ, hence θ ≅ asin y
// Hack: we want: ind = floor(y * 256)
// We deliberately force truncation by adding floating-point numbers whose
// exponents differ greatly. The FPU will right-shift y to match exponents,
// dropping all but the first 9 significant bits, which become the 9 LSBs
// of the resulting mantissa.
// Inspired by a similar piece of C code at
// http://www.shellandslate.com/computermath101.html
double yp = FRAC_BIAS + y;
int ind = (int) Double.doubleToRawLongBits(yp);
// Find φ (a first approximation of θ) from the LUT
double φ = ASIN_TAB[ind];
double cφ = COS_TAB[ind]; // cos(φ)
// sin(φ) == ind / 256.0
// Note that sφ is truncated, hence not identical to y.
double sφ = yp - FRAC_BIAS;
double sd = y * cφ - x * sφ; // sin(θ-φ) ≡ sinθ cosφ - cosθ sinφ
// asin(sd) ≅ sd + ⅙sd³ (from first 2 terms of Maclaurin series)
double d = (6.0 + sd * sd) * sd * ONE_SIXTH;
double θ = φ + d;
// Translate back to correct octant
if (steep) { θ = Math.PI * 0.5 - θ; }
if (negX) { θ = Math.PI - θ; }
if (negY) { θ = -θ; }
return θ;
}
private static final double ONE_SIXTH = 1.0 / 6.0;
private static final int FRAC_EXP = 8; // LUT precision == 2 ** -8 == 1/256
private static final int LUT_SIZE = (1 << FRAC_EXP) + 1;
private static final double FRAC_BIAS =
Double.longBitsToDouble((0x433L - FRAC_EXP) << 52);
private static final double[] ASIN_TAB = new double[LUT_SIZE];
private static final double[] COS_TAB = new double[LUT_SIZE];
static
{
/* Populate trig tables */
for (int ind = 0; ind < LUT_SIZE; ++ ind)
{
double v = ind / (double) (1 << FRAC_EXP);
double asinv = Math.asin(v);
COS_TAB[ind] = Math.cos(asinv);
ASIN_TAB[ind] = asinv;
}
}
}
That might make it : http://sourceforge.net/projects/jafama/
I'm surprised that the built-in Java functions would be so slow. Surely the JVM is calling the native trig functions on your CPU, not implementing the algorithms in Java. Are you certain your bottleneck is calls to trig functions and not some surrounding code? Maybe some memory allocations?
Could you rewrite in C++ the part of your code that does the math? Just calling C++ code to compute trig functions probably wouldn't speed things up, but moving some context too, like an outer loop, to C++ might speed things up.
If you must roll your own trig functions, don't use Taylor series alone. The CORDIC algorithms are much faster unless your argument is very small. You could use CORDIC to get started, then polish the result with a short Taylor series. See this StackOverflow question on how to implement trig functions.
On the x86 the java.lang.Math sin and cos functions do not directly call the hardware functions because Intel didn't always do such a good job implimenting them. There is a nice explanation in bug #4857011.
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4857011
You might want to think hard about an inexact result. It's amusing how often I spend time finding this in others code.
"But the comment says Sin..."
You could pre-store your sin and cos in an array if you only need some approximate values.
For example, if you want to store the values from 0° to 360°:
double sin[]=new double[360];
for(int i=0;i< sin.length;++i) sin[i]=Math.sin(i/180.0*Math.PI):
you then use this array using degrees/integers instead of radians/double.
I haven't heard of any libs, probably because it's rare enough to see trig heavy Java apps. It's also easy enough to roll your own with JNI (same precision, better performance), numerical methods (variable precision / performance ) or a simple approximation table.
As with any optimization, best to test that these functions are actually a bottleneck before bothering to reinvent the wheel.
Trigonometric functions are the classical example for a lookup table. See the excellent
Lookup table article at wikipedia
If you're searching a library for J2ME you can try:
the Fixed Point Integer Math Library MathFP
The java.lang.Math functions call the hardware functions. There should be simple appromiations you can make but they won't be as accurate.
On my labtop, sin and cos takes about 144 ns.
In the sin/cos test I was performing for integers zero to one million. I assume that 144 ns is not fast enough for you.
Do you have a specific requirement for the speed you need?
Can you qualify your requirement in terms of time per operation which is satisfactory?
Check out Apache Commons Math package if you want to use existing stuff.
If performance is really of the essence, then you can go about implementing these functions yourself using standard math methods - Taylor/Maclaurin series', specifically.
For example, here are several Taylor series expansions that might be useful (taken from wikipedia):
Could you elaborate on what you need to do if these routines are too slow. You might be able to do some coordinate transformations ahead of time some way or another.