3

I have this class:

public class Vehicle {
    private float speed;

     public void decelerationSpeed()
     {
         --speed;
     }  
}

Each time decelerationSpeed method have been called speed variable decreased by one.

I need to change decelerationSpeed method this way that, if speed variable reached to zero and decelerationSpeed method have been called the speed value doesn't have to be changed.

In this tutorial I can't use if else or any other conditional operators(I think I have to manipulate with modulo and divide operations).

Michael
  • 13,950
  • 57
  • 145
  • 288

5 Answers5

1

We always want to subtract by one except when our speed is zero so the modulo operation is appropriate as 0 mod y is 0 while for any other number we want x mod y to result in 1. The modulo operation that fits these criteria is x % (x - 1) The two corner cases then are 1 and 2 where 1 would give modulus of 0 and 2 mod 1 would have no effect. So we exclude them from the possible set of values with preliminary addition and subsequent subtraction:

   public void decelerationSpeed()
     {
        speed = speed + 2;
        speed = speed - ((speed) % (speed-1));
        speed = speed - 2;
     }
Anatoly
  • 456
  • 5
  • 13
0

A nice solution using javas floatingpoint to integer-conversion would look like this:

speed -= (int) ((speed / (speed + 1.0) + 0.6));

The basic idea is that java converts floatingpoint numbers to integers by discarding the decimal places. Thus we only need a way to generate a value v, in a way such that 0 <= v < 1, if the input is 0 and 1 <= v < 2 else. speed / (speed + 1.0) provides the property of being 0, if speed is 0, otherwise it's at least 0.5 and at most (mathematically at least) nearly 1. Just shift all of this by 0.6 (to make sure we definitely get above 1) and we've got the require sequence. The rest is just cutting away the decimal places and we're there.

A really ugly (but simpler) way would be the following:

void decrement()
{
    try{
        int throwaway = 1 / speed;
        speed--;
    }catch(ArithmeticException e){
        //just ignore the exception
    }
}
  • This doesn't work if speed can be some value between 0 and 1. – Bubletan Dec 10 '16 at 23:36
  • @Bubletan sry, completely missed that constraint. –  Dec 10 '16 at 23:59
  • @Paul I don't think it is a constraint. The speed values are discreet with respect to whole int steps. So you would never begin or end at some value between 0 and 1 despite speed being a float. This is assuming acceleration also occurs in int steps. – Anatoly Dec 11 '16 at 00:48
  • @Anatoly Well, it's a bit of a weird question, I guess. Clarification by OP would be quite helpful here... –  Dec 11 '16 at 00:56
0

I don't know if bit conversions are allowed but here is a solution:

speed -= 1;

int bits = Float.floatToRawIntBits(speed);
bits &= (bits >>> 31) - 1;
speed = Float.intBitsToFloat(bits);

So, first we get the sign bit (bits >>> 31) and subtract one from it to get a mask: 0xffffffff for positive numbers and 0x00000000 for negative numbers. Using this will change every negative number to +0.

It's not a pretty solution but it works.

Bubletan
  • 3,833
  • 6
  • 25
  • 33
  • `Float.floatToIntBits` uses `If` in its implementation. Don't`Float.floatToRawIntBits` and `Float.intBitsToFloat` do that too? – Omid Dec 10 '16 at 23:07
  • @omid I don't think they do but I might be wrong: http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/native/java/lang/Float.c – Bubletan Dec 10 '16 at 23:12
0

If you can use the Math.sqrt function then its possible using the following equation.

(val+|val|)/2

Basically any negative numbers will subtract from itself becoming 0.

Heres some code showing it

public static float decelerationSpeed(float speed) {
    speed -= 1; // subtract
    // use (val+|val|)/2 to zero out any negative numbers. Divide by 2 to return to origional number
    return (float) (speed+Math.sqrt(speed*speed))/2f;
}

public static void main(String [] args) throws Exception {
    System.out.println(assertF(decelerationSpeed(-10), 0));
    System.out.println(assertF(decelerationSpeed(10), 9));

    System.out.println(assertF(decelerationSpeed(-2), 0));
    System.out.println(assertF(decelerationSpeed(2), 1));

    System.out.println(assertF(decelerationSpeed(-1), 0));
    System.out.println(assertF(decelerationSpeed(1), 0));

    System.out.println(assertF(decelerationSpeed(-0), 0));
    System.out.println(assertF(decelerationSpeed(0), 0));
}

public static float assertF(float actual, float expected) {
    if(actual != expected) throw new IllegalStateException("Expected "+expected+" but got "+actual);
    return actual;
}
ug_
  • 11,267
  • 2
  • 35
  • 52
-2

This is how I would answer this question. Works passing in int, short, float, or double, etc.:

public class HelloWorld
{
  private static float speed = 1113; // initial speed
  private static short smallIncrement = 13;

  public static void main(String[] args)
  {
      decelerateAndReturnSpeed(2.33); // prints 1110.67
      decelerateAndReturnSpeed(7.33f); // prints 1103.3401
      decelerateAndReturnSpeed(113); // prints 990.3401
      decelerateAndReturnSpeed(smallIncrement); // prints 977.3401
  }

  public static float decelerateAndReturnSpeed(double vAmt)
  {
    speed -= vAmt;
    if (speed < 0) speed = 0;
    System.out.println(speed);
    return speed;
  }
}

Now, this is because the compiler computes like this, with a implicit cast:

speed = (float)(speed -vAmt);  // same as speed =- vAmt
djangofan
  • 28,471
  • 61
  • 196
  • 289