if I add or subtract two short values, how can I tell if I would need to flag a carry condition
You can do the addition or subtraction using a larger type such as int, cast it to a short, and test if the cast changes the value.
int i = s1 + s2;
short s = (short)i;
if (i != s) { /* overflow */ }
In the case of adding and subtracting only, arithmetic overflow has occurred when both operands are positive and the result is negative and vice versa.
class OverflowTest
{
public static void main (String[] args)
{
System.out.println(isOverflow((short)32767, (short)32767, '+'));
System.out.println(isOverflow((short)-32767, (short)-32767, '+'));
System.out.println(isOverflow((short)32767, (short)-32767, '+'));
}
private static boolean isOverflow(short a, short b, char op) {
short c = (op == '+') ? (short)(a+b) : (short)(a-b);
if((a > 0 && b > 0 && c < 0) || (a < 0 && b < 0 && c > 0))
return true;
return false;
}
}
Related
I was wondering how to check if two out of three values are the same. My code right now is:
public static boolean twoOutOfThree(int a, int b, int c) {
if ((a == b) || (b == c) || (a == c)) {
return true;
}
return false;
}
This passes all of the tests that are true however when I test it for (0,0,0), it comes back as true instead of false. Any suggestions on what I'm doing wrong?
When all 3 are the same, then a == b obviously is also true. So each 3 of the cases also needs to check that the 3rd one is different. So you need to change
(a == b || b == c || a == c)
to
(a == b && b != c) || (b == c && a !=c ) || (a == c && b != c))
Additional tip
Functions of this form:
if (condition) {
return true;
} else {
return false;
}
Can be written much shorter by just doing
return condition;
So the end result is this:
public static boolean twoOutOfThree(int a, int b, int c) {
return ((a == b && b !=c ) || (b == c && a !=c ) || (a == c && b !=c));
}
Here is a non-optimized solution.
The Set will get rid of duplicates, then just check its final size.
return new HashSet<Integer>(Arrays.asList(a,b,c)).size() == 2;
You could add an extra case to your if statement:
((a==b) || (b==c) || (a==c) && !(a == b & b == c))
There is probably a more efficient way to do this.
You can add a variable called "count" for example , if any value is equal to another then you increment the count by 1 and then you can check if count is equal to 2
You can count as the following solution
public static boolean twoOutOfThree(int a, int b, int c) {
int count = 0;
if (a == b) {
count += 1;
}
if (b == c) {
count += 1;
}
if (c == a)
count += 1;
}
if (count == 2) {
return true;
} else {
return false;
}
}
Just create a Set and add your values in the set. Set always holds unique values only. So if you have 3 numbers and add them to a set and your set length is 3 that none of the numbers are equal to each other. If the length is 2 then 2 numbers where equal and if the length is 1 then all 3 are equal
return !(
(
(a==b)&&(b==c)
) ||
(
(a!=b)&&(b!=c)&&(a!=c)
)
);
Only 10 operators made of
3 AND
1 OR
1 NOT
5 comparisons
I don't know if this is fastest. But if CPU core has multiple ALUs each doing comparisons in parallel, then this could get a boost.
i need help on a verification on a string
I have to write a method that verify if 2 parameters of the method have the same length and if the second one have numbers between 0 and 3.
Let's see what i wrote :
public static boolean coupEstValide( String combinaison, String coup ){
boolean res = true;
if(combinaison.length() == coup.length()){
int i = 0;
while(i < coup.length() && res == true){
char t = coup.charAt(i);
if(t <= 0 && t >= 3)
res = false;
i++;
}
}
return res;
in my opinion, this should work... But if i do this :
coupEstValide("555", "104");
it should tell me false but it it's telling me it's true.
Do you guys see what's wrong ?
Thanks
When you compare Character with an integer actually ASCII value of that character gets compared with that integer. That's why you keep getting true.
So as already suggested in the comments you should compare it either as if(t >= '0' && t <= '3') or use any Utility method of java.lang such as Character.compare(char lhs, char rhs).
Hope this would be helpful.
Enjoy!
A few of problems in your code:
If the lengths are different, you are still returning true!
Strings are composed of characters. Their value is their character code. 0 to 3 are 48 to 51, respectively. Use character constants not integer constants: if (t == '0') will check if t is the character "0".
Your logic for the comparison isn't right anyways. Using your original (incorrect) example with integers, and correcting from <= and >= based on your comments: if (t < 0 && t > 3) will never be true, t cannot simultaneously be less than 0 and greater than 3. I'll leave the correct boolean statement as an exercise to the reader (hint: or).
Alright, i fixed the problem.
So as you said, i should've use
if(t < '0' || t > '3')
And to fix the problem of the time both are not the same size, i added an else.
So the full code is that :
public static boolean coupEstValide( String combinaison, String coup ){
boolean res = true;
if(combinaison.length() == coup.length()){
int i = 0;
while(i < coup.length() && res == true){
char t = coup.charAt(i);
if(t < '0' || t > '3')
res = false;
i++;
}
}
else
res = false;
return res;
}
Thanks for your help guys !
This would never true. A number can not be less and equal to zero and at the same time greater and equal to 3.
if(t <= 0 && t >= 3)
If you want to evaluate whether a character is between 0 and 3 you must use this:
if(t >= '0' && t <= '3')
Now if you want to evaluate if the character is not between 0 and 3 then try this:
if (t <'0' || t> '3')
String coup = "053";
boolean res = true;
int i = 0;
while (i < coup.length() && res == true) {
System.out.println(coup.length());
int t = Integer.parseInt(coup.charAt(i) + "");
System.out.println("T is " + t);
if (t <= 0 || t >= 3) {
res = false;
i++;
}
System.out.println("Value i " + i);
System.out.println("Value of the Res at last" + res);
}
may be this could be helpful try to convert it to the integer
according to your code
String coup = "053";
boolean res = true;
int i = 1;
while (i < coup.length() && res == true) {
System.out.println(coup.length());
//int t = Integer.parseInt(coup.charAt(i) + "");
char t = coup.charAt(i);
System.out.println("T is " + t);
if (t <= 0 || t >= 3) {
res = false;
i++;
}
System.out.println("Value i " + i);
System.out.println("Value of the Res at last" + res);
}
If I change the else if portion of this code to an else statement it runs without any problems so I get how to make it run. What I'm a little confused about is why I get a missing return statement error when it is in its current form. My return is dependent on the value of the boolean variable of negative. I covered the true and false states, isn't that good enough to cover everything?
Or is it that I always have to have a return statement within an else or to add a meaningless return true to the bottom of my function for the compiler to accept my code as covering every case?
import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone
{
public boolean posNeg(int a, int b, boolean negative) {
if (!negative) {
return (a < 0 && b > 0) || (a > 0 && b < 0);
}
else if (negative) {
return (a < 0 && b < 0);
}
}
public static void main (String[] args) throws java.lang.Exception
{
}
}
When the compiler sees else if without an else or a trailing return statement, it cannot be certain that all control paths will lead to a valid return statement.
The compiler can be smart at times, but it can't be smart in this situation (nor should it be).
This behavior is helpful in your example: there's absolutely no reason for you to use an else if in this situation. A simple else is easier to read, more concise, and less error prone.
An else is very expressive in this case. It means "the opposite of the if clause" which will still be the case if the code changes in the future.
Your current code would be more likely to contain and/or introduce a bug if the compiler allowed it.
Here's how I would rewrite the method body:
if (negative) {
return (a < 0 && b < 0);
}
else {
return (a < 0 && b > 0) || (a > 0 && b < 0);
}
In general you should prefer if (negative) over if (!negative) unless there's a compelling reason (ie readability) to do otherwise.
Also, a lot of people (including myself) try to put the most simple clause first in an if/else statement. Making your code easy to read is a good thing.
Check out StephenC's answer for a technical explanation and more background about why the compiler behaves this way.
Other questions have explained what the error message means from an intuitive perspective. However the "The compiler is smart, but not perfect!" comment is missing the point.
In fact, the Java compiler is calling your example an error because the Java Language Specification requires it to call it an error. The Java compiler is not permitted to be "smart" about this.
Here is what the JLS (for Java 71) actually says, and how it applies to a simplified version of the incorrect example, and then a corrected version.
"If a method is declared to have a return type, then a compile-time error occurs if the body of the method can complete normally (JLS 14.1). In other words, a method with a return type must return only by using a return statement that provides a value return; it is not allowed to "drop off the end of its body". " - JLS 8.4.7
(Read JLS 14.1 for the definition of "normal completion" ...)
And the rules for deciding whether a "normal" completion is possible are the reachability rules in JLS 14.21. And they say:
"An if-then statement can complete normally iff it is reachable."
"An if-then-else statement can complete normally iff the then-statement can complete normally or the else-statement can complete normally."
"A break, continue, return, or throw statement cannot complete normally."
(Where 'iff' means "if and only if" ...)
Consider a simplified version of the example:
public int test(boolean a) {
if (a) {
return 1;
}
else if (!a) {
return 0;
}
}
In this example, the else-statement is an if-then which can complete normally by rule #1. Therefore, by rule #2, the if-then-else statement can also complete normally. But that is a compilation error, because JLS 8.4.7 says that a method with a return type cannot complete normally.
But if you change the example to this ...
public int test(boolean a) {
if (a) {
return 1;
}
else {
return 0;
}
}
Now by rule #3, both the if-statement and the else-statement cannot complete normally. So by rule #2, the entire if-then-else cannot complete normally. That is what it required by JLS 8.4.7 ... therefore no compilation error.
1 - The Java 8 JLS will say essentially the same thing, though the section numbers may be different ...
I think you already know that the second if is redundant.
if (negative) is interpreted context-free, which means that the compiler ignores that if(!negative) has already been handled.
if => else if => where is the else condition?
For a return statement, all branches (conditions) must be handled.
You could do:
if (!negative)
return (a < 0 && b > 0) || (a > 0 && b < 0);
return (a < 0 && b < 0);
or:
if (!negative)
return (a < 0 && b > 0) || (a > 0 && b < 0)
else
return (a < 0 && b < 0);
or (my preferred way):
return negative ? (a < 0 && b < 0) : (a < 0 && b > 0 || a > 0 && b < 0)
However, I'd recommend to avoid the negative condition, it's harder for the human brain in complex scenario. Even some Java IDEs like IntelliJ helps to find those patterns to fix them.
You'd end up with:
if (negative)
return (a < 0 && b < 0);
else
return (a < 0 && b > 0) || (a > 0 && b < 0);
You do not need "if (negative) {}" in the "else" brace
You should have a return in all your branches.
public boolean posNeg(int a, int b, boolean negative) {
if (!negative) {
return (a < 0 && b > 0) || (a > 0 && b < 0);
}
else if (negative) {
return (a < 0 && b < 0);
}
}
The method above logically has a return in all branches, but technically it does not. We like the Java compiler to be fast, therefore it is undesirable to have a Java compiler analyzing semantically the code.
public boolean posNeg(int a, int b, boolean negative) {
if (!negative) {
return (a < 0 && b > 0) || (a > 0 && b < 0);
}
else {
return (a < 0 && b < 0);
}
}
The method above has a return in all the branches.
public boolean posNeg(int a, int b, boolean negative) {
if (!negative) {
return (a < 0 && b > 0) || (a > 0 && b < 0);
}
return (a < 0 && b < 0);
}
However, as you can see above, you do not even need the else, because if the code ever reaches the second return, then negative is certainly false, as if it was true, the first return would end the algorithm.
public boolean posNeg(int a, int b, boolean negative) {
return ((negative) && (a < 0 && b < 0)) || ((!negative) && (a < 0 && b > 0) || (a > 0 && b < 0));
}
The method above is a one-liner.
public boolean posNeg(int a, int b, boolean negative) {
return ((negative) && (a < 0 && b < 0)) || ((!negative) && ((a < 0) == (b > 0)));
}
The method above uses the fact that in the second case the positivity of a is equal with the negativity of b.
Here's the question: Given 2 int values greater than 0, return whichever value is nearest to 21 without going over. Return 0 if they both go over.
blackjack(19, 21) → 21
blackjack(21, 19) → 21
blackjack(19, 22) → 19
What I have so far:
public int blackjack(int a, int b) {
if (a>21 && b>21){
return 0;
}
if (a<21 && b>21){
return a;
}
if (b<21 && a>21){
return b;
}
if (21-a < 21-b){
return a;
}
return b;
}
This question is from codingbat.com, and for all the tests that it shows, this code works, but when it finishes and displays "other tests", this code fails. I suppose there's a certain situation where this wouldn't work, but I can't think of it right now. Any thoughts?
public int blackjack(int a, int b) {
// if both a and b are outside the valid range
if (a > 21 && b > 21)
return 0;
// if a is within the valid range but b is not
if (a <= 21 && b > 21)
return a;
// if b is within the valid range but a is not
if (b <= 21 && a > 21)
return b;
// if both a and be are within the valid range
return (a-b >= 0) ? a : b;
// Alternative: return Math.max(a, b); ---as per SimonT in the comment
}
So I guess your issue is that you didn't include 21 in your conditions.
If a=21, b=22, then it will return b which is not correct.
You forgot to specify the = operation in your condition. Change 2nd and 3rd condition to :
if (a<=21 && b>21){
return a;
}
if (b<=21 && a>21){
return b;
}
Hi all I was wondering if there is a way to implement this method without casting to a wider data type (e.g. long, double, etc)?
CanTimes(int a, int b){
returns true if a * b is within the range of -2^31 to 2^31-1, else false;
}
For example, we could implement one for the method CanAdd (without casts) as such:
public static boolean CanPlus(int a, int b) {
if (b >= 0) {
return a <= Integer.MAX_VALUE - b
} else {
return a >= Integer.MIN_VALUE - b
}
}
Implementation language is Java, though of course this is more of a language-agnostic problem.
I was thinking if there's some logic we can employ to decide if a * b fits the range of an integer without casting it to a wider data type?
Solution ! based on Strelok's comment:
public static boolean CanTimes(int a, int b) {
if (a == 0 || b == 0) {
return true;
}
if (a > 0) {
if (b > 0) {
return a <= Integer.MAX_VALUE / b;
} else {
return a <= Integer.MIN_VALUE / b;
}
} else {
if (b > 0) {
return b <= Integer.MIN_VALUE / a;
} else {
return a <= -Integer.MAX_VALUE / b;
}
}
}
As per my comment, here is the adapted version, with some unit tests:
public static int mulAndCheck( int a, int b )
{
int ret;
String msg = "overflow: multiply";
if ( a > b )
{
// use symmetry to reduce boundry cases
ret = mulAndCheck( b, a );
}
else
{
if ( a < 0 )
{
if ( b < 0 )
{
// check for positive overflow with negative a, negative b
if ( a >= Integer.MAX_VALUE / b )
{
ret = a * b;
}
else
{
throw new ArithmeticException( msg );
}
}
else if ( b > 0 )
{
// check for negative overflow with negative a, positive b
if ( Integer.MIN_VALUE / b <= a )
{
ret = a * b;
}
else
{
throw new ArithmeticException( msg );
}
}
else
{
// assert b == 0
ret = 0;
}
}
else if ( a > 0 )
{
// assert a > 0
// assert b > 0
// check for positive overflow with positive a, positive b
if ( a <= Integer.MAX_VALUE / b )
{
ret = a * b;
}
else
{
throw new ArithmeticException( msg );
}
}
else
{
// assert a == 0
ret = 0;
}
}
return ret;
}
#Test( expected = ArithmeticException.class )
public void testOverflow()
{
mulAndCheck( Integer.MAX_VALUE, Integer.MAX_VALUE );
}
#Test( expected = ArithmeticException.class )
public void testOverflow1()
{
mulAndCheck( Integer.MIN_VALUE, Integer.MAX_VALUE );
}
#Test
public void testTimesMinus1()
{
Assert.assertEquals( Integer.MIN_VALUE + 1, mulAndCheck( Integer.MAX_VALUE, -1 ) );
Assert.assertEquals( Integer.MAX_VALUE, mulAndCheck( Integer.MIN_VALUE + 1, -1 ) );
}
You can do the multiplication and then check whether dividing by one factor still gives the other.
EDIT
The above doesn't work all the time, as Dietrich Epp points out; it fails for -1 and Integer.MIN_VALUE. I don't know if there are any other edge cases. If not, then it would be easy to check for this one case.
Since the multiplication of a*b is the same as a+a+a+... repeated b times (and vice-versa), you can do something like this:
(I renamed your CanMultiple() function to isIntMultiplication(), since I think its more clear )
public boolean isIntMultiplication(int a, int b) {
// signs are not important in this context
a = Math.abs(a);
b = Math.abs(b);
// optimization: I want to calculate a*b as the sum of a by itself repeated b times, so make sure b is the smaller one
// i.e., 100*2 is calculated as 100+100 which is faster than summing 2+2+2+... a hundred times
if (b > a) { int swap = a; a = b; b = swap; }
int n = 0, total = a;
while(++n < b) {
if (total <= Integer.MAX_VALUE - a) {
total += a;
} else {
return false;
}
}
return true;
}
You see it in action:
// returns true, Integer.MAX_VALUE * 1 is still an int
isIntMultiplication(Integer.MAX_VALUE, 1);
// returns false, Integer.MAX_VALUE * 2 is a long
isIntMultiplication(Integer.MAX_VALUE, 2);
// returns true, Integer.MAX_VALUE/2 * 2 is still an int
isIntMultiplication(Integer.MAX_VALUE/2, 2);
// returns false, Integer.MAX_VALUE * Integer.MAX_VALUE is a long
isIntMultiplication(Integer.MAX_VALUE, Integer.MAX_VALUE);
This solution does not use long types, as required.
Mathematically, the sum of the log-base-2 should be less than 232. Unfortunately, Math doesn't give us log base 2, but this is still simple enough:
static boolean canMultiply(int a, int b) {
return Math.log(Math.abs(a)) + Math.log(Math.abs(b)) <= Math.log(Integer.MAX_VALUE);
}
EDITED: Due to (fair) flak, how about this simple approach that addresses OP's question exactly?
static boolean canMultiply(int a, int b) {
return a == 0 || ((a * b) / a) == b;
}
If there's an overflow, dividing by the original number won't bring us back to starting number.
Importantly, this will work for longs, which can't be cast up.