16 비트 부호없는 정수를 2의 제곱으로 나눠 계산해야하므로 32 비트 플로트 (표준 IEEE 형식)가됩니다. 이것은 임베디드 시스템에 있고 루틴은 반복적으로 사용되므로 (float)x/(float)(1<<n)
보다 나은 것을 찾고 있습니다. 또한 C 컴파일러는 꽤 제한적입니다 (수학 라이브러리, 비트 필드, reinterpret_cast 등).2의 거듭 제곱으로 플로트 결과
답변
당신이 다음 갈 수있는 확실한 방법을 만지작 일부 비트를 꺼리지 않는 경우^n은 2로 분할을 달성하기 위해 플로트와 지수 비트에서 빼기 n으로 정수를 변환하는 것입니다 :
y = (float)x; // convert to float
uint32_t yi = *(uint32_t *)&y); // get float value as bits
uint32_t exponent = yi & 0x7f800000; // extract exponent bits 30..23
exponent -= (n << 23); // subtract n from exponent
yi = yi & ~0x7f800000 | exponent; // insert modified exponent back into bits 30..23
y = *(float *)&yi; // copy bits back to float
x = 0에 대해서는 실패하므로 변환 전에 x> 0을 확인해야합니다.
총 비용은 int-float 변환과 소수의 정수/비트 연산/연산입니다. 유니온을 사용한다면 별도의 int/float 표현을 피하고 float에서 직접 작업하면됩니다.
고마워요. 이 무언가에 대해서도 생각하고 있었지만 캐스팅을하는 법을 몰랐습니다. 그리고 당신은 uint32_t 지수 = yi & 0x7f800000을 의미한다고 가정합니다; 다시 한 번 감사드립니다 !!! – CoderSS
죄송합니다 - 예 - 오타가 수정되었습니다. –
아직 시스템을 점검 할 수 없으므로 여기에 시스템이 없습니다. 그러나 일부 컴파일러는 y = (float) x 일 때 x를 정규화 할 것이라고 걱정해야합니다 (예 : x = 15, 1.5E + 1이 15E + 0 대신 y에 저장 됨). 그런 다음 수정 지수 부분이 더 이상 올바르게 작동하지 않습니다. – CoderSS
ldexpf(x, -n)
을 사용하십시오. 이 함수는 정확히을 수행하기 위해 C 표준에 정의되어 있습니다. x • 2 -n을 반환하십시오. 따라서 알맞은 컴파일러가 이에 대한 좋은 코드를 제공합니다. 이 작업을 수행하려면 수학 라이브러리 나이 작업을 인라인 코드로 최적화하는 컴파일러가 필요합니다.
컴파일시에 n
을 알고있는 경우 x * (1.f/(1<<n))
을 고려할 수도 있습니다. 좋은 컴파일러는 컴파일시에 (1.f/(1<<n))
을 계산하므로 실행 코드는 x
에서 float
으로 변환하고 상수로 곱하십시오. 컴파일러가 ldexpf(x, -n)
을 최적화하지 않을 경우 ldexpf(x, -n)
에 대해 생성 된 코드보다 빠를 수도 있습니다.
은 "사용자가 지정한 이외의 멋진 답변이 될 것입니다."또한 C 컴파일러는 꽤 제한적입니다 (수학 라이브러리, 비트 필드, reinterpret_cast 등).이 함수는 수학 라이브러리에 있습니다. – CashCow
빠르고 쉬운 용액의 요소 n 번째 하여 다음 곱셈 x
n >= 0
2 -n의 부동 소수점 값의 테이블 (n
상한 31 해결? 기능) 등을 미리 계산하는 표.
코드가 부동 소수점 곱셈을 에뮬레이트하는 경우 CPU가이를 직접 지원하지 않기 때문에 이것이 가장 빠를 수 없습니다.
그러나 정수 계산을 사용하는 것이 더 빠릅니다.
예 (가정 IEEE-754 32 비트 수레) :
#include <limits.h>
#include <string.h>
#include <stdio.h>
#define C_ASSERT(expr) extern char CAssertExtern[(expr)?1:-1]
C_ASSERT(CHAR_BIT == 8);
C_ASSERT(sizeof(float) == 4);
C_ASSERT(sizeof(int) == 4);
float div(int x, unsigned n)
{
float res;
unsigned e = 0;
unsigned sign = x < 0;
unsigned m = sign ? -x : x;
if (m)
{
while (m >= (1u << 24))
m >>= 1, e++;
while (m < (1u << 23))
m <<= 1, e--;
e += 0x7F + 23;
e -= n; // divide by 1<<n
m ^= 1u << 23; // reset the implicit 1
m |= (e & 0xFF) << 23; // mix in the exponent
m |= sign << 31; // mix in the sign
}
memcpy(&res, &m, sizeof m);
return res;
}
void Print4Bytes(unsigned char buf[4])
{
printf("%02X%02X%02X%02X ", buf[3], buf[2], buf[1], buf[0]);
}
int main(void)
{
int x = 0x35AA53;
int n;
for (n = 0; n < 31; n++)
{
float v1 = (float)x/(1u << n);
float v2 = div(x, n);
Print4Bytes((void*)&v1);
printf("%c= ", "!="[memcmp(&v1, &v2, sizeof v1) == 0]);
Print4Bytes((void*)&v2);
printf("%14.6f %14.6f\n", v1, v2);
}
return 0;
}
출력 (ideone) :
4A56A94C == 4A56A94C 3517011.000000 3517011.000000
49D6A94C == 49D6A94C 1758505.500000 1758505.500000
4956A94C == 4956A94C 879252.750000 879252.750000
48D6A94C == 48D6A94C 439626.375000 439626.375000
4856A94C == 4856A94C 219813.187500 219813.187500
47D6A94C == 47D6A94C 109906.593750 109906.593750
4756A94C == 4756A94C 54953.296875 54953.296875
46D6A94C == 46D6A94C 27476.648438 27476.648438
4656A94C == 4656A94C 13738.324219 13738.324219
45D6A94C == 45D6A94C 6869.162109 6869.162109
4556A94C == 4556A94C 3434.581055 3434.581055
44D6A94C == 44D6A94C 1717.290527 1717.290527
4456A94C == 4456A94C 858.645264 858.645264
43D6A94C == 43D6A94C 429.322632 429.322632
4356A94C == 4356A94C 214.661316 214.661316
42D6A94C == 42D6A94C 107.330658 107.330658
4256A94C == 4256A94C 53.665329 53.665329
41D6A94C == 41D6A94C 26.832664 26.832664
4156A94C == 4156A94C 13.416332 13.416332
40D6A94C == 40D6A94C 6.708166 6.708166
4056A94C == 4056A94C 3.354083 3.354083
3FD6A94C == 3FD6A94C 1.677042 1.677042
3F56A94C == 3F56A94C 0.838521 0.838521
3ED6A94C == 3ED6A94C 0.419260 0.419260
3E56A94C == 3E56A94C 0.209630 0.209630
3DD6A94C == 3DD6A94C 0.104815 0.104815
3D56A94C == 3D56A94C 0.052408 0.052408
3CD6A94C == 3CD6A94C 0.026204 0.026204
3C56A94C == 3C56A94C 0.013102 0.013102
3BD6A94C == 3BD6A94C 0.006551 0.006551
3B56A94C == 3B56A94C 0.003275 0.003275
@EricPostpischil OP는 '수학이 없다'고 말했다. –
- 1. 우리는 항상 상수를 2의 거듭 제곱으로 선언합니까? 우리가 왜
- 2. opencv dft는 2의 거듭 제곱으로 이미지 크기가 올바르게 작동합니다.
- 3. 왜 바이트가 2의 제곱으로 말합니까?
- 4. 왜 InSampleSize가 2의 거듭 제곱이어야합니까?
- 5. 자바는 비트 시프트에 2의 제곱으로 나눗셈을 최적화합니까?
- 6. 2의 거듭 제곱의 결과로 값 분해
- 7. 정수가 C에서 2의 거듭 제곱인지 확인
- 8. 2의 거듭 제곱의 합으로 숫자를 인쇄하십시오.
- 9. 2의 거듭 제곱에 가장 가까운 정수를 찾아
- 10. 왜 링 버퍼 크기가 2의 거듭 제곱이어야합니까?
- 11. 사용자 입력에서 2의 거듭 제곱을 계산하십시오.
- 12. 무엇이 비트 OR 및 AND에 대해 2의 거듭 제곱을 사용합니까?
- 13. 에는 2의 제곱으로 증가하는 ID 또는 시퀀스를 생성하는 방법이 있습니까?
- 14. LWJGL에서 2의 힘이 아닌 텍스처는 어떻게 사용합니까?
- 15. 텍스처를 한 파일에 넣는 법 (2의 거듭 제곱)
- 16. 크기가 2의 거듭 제곱이 아닌 정수는 의미가 있습니까?
- 17. 2의 거듭 제곱의 합을 사용하여 소수점 이하를 2 진수로 변환
- 18. 크기가 2의 거듭 제곱이 아닐 때 벡터 합계가 감소합니까?
- 19. 2의 거듭 제곱에 대해 세트 분할을위한 다항식 시간 알고리즘?
- 20. Numpy (Python)에서 FFT가 2의 거듭 제곱이 아닐 때
- 21. 2의 거듭 제곱을 구하는 가장 빠른 방법은 무엇입니까?
- 22. 알파벳을 보낼 때 2의 거듭 제곱의 직렬 데이터 만 수신
- 23. 검색 결과 SublimeText 2의 패널
- 24. 아틀라스의 TextureRegions는 2의 제곱이어야합니까?
- 25. 동일한 플로트 계산에 대한 다른 결과
- 26. 표시 플로트 결과 더 읽기 2008
- 27. Python에서 최소 제곱으로 문제가 발생했습니다.
- 28. ArrayList의 내용을 2 요소의 제곱으로 합하는 가장 효율적인 방법은 무엇입니까?
- 29. Struts 2의 INPUT 결과 페이지로 돌아 가기
- 30. JSF 2의 현재 결과 얻는 방법
는 좀 컴파일러 내장 함수가있는 경우가 아니면, 조립하지 않고 더 나은 얻을 수 있습니다 의심한다. 또한 프로필, 프로필, 프로필. – Antimony
나는 "float x/float (y)보다 낫다"는 말을 사용합니다. 여기서 y는 2의 거듭 제곱입니까? 또한 "더 나은"의미는 무엇입니까? – Xyzk
"더 나은"성능은 내가 찾고있는 것입니다 – CoderSS