abs 함수나 if 스테이트먼트를 사용하지 않고 절대값을 얻는다.
어떻게 하면 정수의 절대값을 얻을 수 있을까 생각 중이었는데if
스테이트먼트도abs()
처음에는 왼쪽 시프트 비트를 사용하고 있었습니다.<<
음의 부호를 범위 밖으로 끌어낸 후 비트를 원래 위치로 되돌리려고 합니다만, 유감스럽게도, 저는 효과가 없습니다.왜 안 되는지 다른 방법을 알려주세요.
int abs(int v)
{
return v * ((v>0) - (v<0));
}
이 코드는 다음 값을 곱합니다.v
와 함께-1
또는1
복근이 생기다.따라서 괄호 안은 다음 중 하나가 됩니다.-1
또는1
.
한다면v
긍정적인 표현입니다.(v>0)
진실이며, 가치 있는1
하는 동안에(v<0)
false 입니다(false의 경우 값 0).따라서 언제v
긍정적이다((v>0) - (v<0)) = (1-0) = 1
전체 표현은 다음과 같습니다.v * (1) == v
.
한다면v
이 표현은 부정적이다.(v>0)
false이며, 가치가 있습니다.0
하는 동안에(v<0)
true(값 1)입니다.따라서, 음의 경우v
,((v>0) - (v<0)) = (0-1) = -1
전체 표현은 다음과 같습니다.v * (-1) == -v
.
언제v == 0
,둘다요.(v<0)
그리고.(v>0)
는 0으로 평가되며, 다음과 같이 남습니다.v * 0 == 0
.
int v; // we want to find the absolute value of v
unsigned int r; // the result goes here
int const mask = v >> sizeof(int) * CHAR_BIT - 1;
r = (v + mask) ^ mask;
이 코드를 C로 입력해 보면 동작합니다.
int abs(int n){
return n*((2*n+1)%2);
}
이 답변이 도움이 되기를 바랍니다.
브런치리스:
int abs (int n) {
const int ret[2] = { n, -n };
return ret [n<0];
}
주 4.7 통합 변환 / 4: [...] If the source type is bool, the value false is converted to zero and the value true is converted to one.
분기 또는 곱셈 없음:
int abs(int n) {
int mask = n >> 31;
return (mask & -n) | (~mask & n);
}
32비트 부호 정수(Java)를 가정하면 다음과 같이 쓸 수 있습니다.
public static int abs(int x)
{
return (x + (x >> 31)) ^ (x >> 31);
}
곱셈도 없고, 분기도 없어요.
그건 그렇고.return (x ^ (x >> 31)) - (x >> 31);
그것도 괜찮겠지만 특허가 있어요.네!
주의: 이 코드는 조건문(8bit Verison)보다 10배 이상 오래 걸릴 수 있습니다.이는 하드웨어 프로그래밍 시스템 C 등에 유용할 수 있습니다.
이건 못 봤어2개의 보완 표현과 32비트 int의 경우
( n >> 31 | 1 ) * n
왼쪽 사인 비트를 밖으로 이동시키고 오른쪽 사인 비트를 다시 제자리로 이동시키는 데는 여러 가지 이유가 있습니다(v << 1 >> 1
):
- 음수 값을 가진 부호 있는 유형을 왼쪽 이동하면 동작이 정의되지 않으므로 전혀 사용하지 않아야 합니다.
- 가치를 부여하다
unsigned
원하는 효과를 얻을 수 있습니다.(unsigned)v << 1 >> 1
패딩 비트가 존재하지 않는 경우 부호 비트를 삭제합니다만, 결과값은 의 절대값입니다.v
오늘날에는 매우 드물지만, 부호+규모 표기를 가진 시스템에만 해당됩니다.유비쿼터스 2의 보완 아키텍처에서는 부정적인 가치를 얻을 수 있습니다.v
이INT_MAX+1-v
안타깝게도 Hasturkun의 솔루션에는 구현 정의 동작이 있습니다.
다음은 서명된 값에 대한 2의 보완 표현을 가진 시스템에 대해 완전히 정의된 변형입니다.
int v; // we want to find the absolute value of v
unsigned int r; // the result goes here
unsigned int mask = -((unsigned int)v >> (sizeof(unsigned int) * CHAR_BIT - 1));
r = ((unsigned int)v + mask) ^ mask;
이건 어때?
#include <climits>
long abs (int n) { // we use long to avoid issues with INT MIN value as there is no positive equivalents.
const long ret[2] = {n, -n};
return ret[n >> (sizeof(int) * CHAR_BIT - 1)]; // we use the most significant bit to get the right index.
}
언어에서 bool이 int cast(C/C++ like)를 허용하는 경우:
float absB(float n) {
return n - n * 2.0f * ( n < 0.0f );
}
다음을 시도해 보십시오.
int abs(int n)
{
return sqrt(n*n);
}
어때?
value = value > 0 ? value: ~value + 1
음수가 양수에 대한 2의 보수로 저장되고, 먼저 1의 보수를 만들고 1을 더함으로써 2의 보수를 만들 수 있다는 사실에 기초한다.
5 -> 0000 0101b
-5 -> (1111 1010b) + 1 -> 1111 1011b
제가 한 일은 기본적으로 이걸 되돌리는 거였어요
-5 -> 1111 1011b
5 -> (0000 0100b) + 1 -> 0000 0101b
조금 늦은 건 알지만 같은 문제가 생겨서 여기 도착했어요. 이게 도움이 됐으면 좋겠네요.
나눗셈(및 더 넓은 산술)을 사용하여 "if"를 형성합니다.효율적이지는 않지만, 지점은 없습니다.
int abs_via_division(int v) {
// is_neg:0 when v >= 0
// 1 when v < 0
int is_neg = (int) ((4LL * v) / (4LL * v + 1));
return v * (1 - is_neg*2);
}
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★int
때long long
넓다int
with with with with , with with with with의 일반적인 |INT_MIN|
.
3진 연산자를 사용합니다.
y = condition ? value_if_true : value_if_false;
사용자가 고려하는 방식으로 부호 있는 정수를 이동하는 비트는 정의되지 않은 동작이므로 옵션이 아닙니다.대신 다음과 같이 할 수 있습니다.
int abs(int n) { return n > 0 ? n : -n; }
.if
문장은 그냥 조건식일 뿐이에요
또 이 있습니다.abs()
논리식/조건식도 없는 경우:여기서 int는 32비트 정수라고 가정합니다..(1 - 2 * sign_bit)
sign_bit = 1 / 0 to -1 / 1
.
unsigned int abs_by_pure_math( int a ) {
return (1 - (((a >> 31) & 0x1) << 1)) * a;
}
비트 시프트는 (원칙적으로) 구현 정의되지만, 보다 넓은 부호 정수 타입으로 변환하면 부호 비트가 확장됩니다.hi-bits를 정수로 해석하면 0 또는 -1이 되어 2의 보수를 반전할 수 있습니다.
int32_t abs(int32_t in)
{
int64_t in64 = (int64_t)in;
int32_t* ptr = (int32_t*)&in64;
int32_t hi = *(++ptr); // assumes little-endian
int32_t out = (in ^ hi) - hi;
return out;
}
위의 메커니즘은 최적화가 유효하게 된 상태에서 Naigive 구현을 컴파일한 결과입니다.
mov eax,ecx
cdq
xor eax,edx
sub eax,edx
언급URL : https://stackoverflow.com/questions/9772348/get-absolute-value-without-using-abs-function-nor-if-statement
'programing' 카테고리의 다른 글
글로벌 vue 컴포넌트에서 메서드를 호출하려면 어떻게 해야 합니까? (0) | 2022.07.03 |
---|---|
NoClassDefFoundError와 ClassNotFoundException의 원인과 차이점은 무엇입니까? (0) | 2022.07.03 |
vue $nextTick을 사용하는 것과 vuejs에서 setTimeout 0을 사용하는 것의 차이점은 무엇입니까? (0) | 2022.07.02 |
동일한 catch 절에서 여러 Java 예외를 잡을 수 있습니까? (0) | 2022.07.02 |
가져온 후 내보낸 모듈이 정의되지 않았습니다. (0) | 2022.07.02 |