cpp에서 precision 변경...

dorado2의 이미지

현재 redhat 7.1, gcc 2.96에서 작업중입니다.

윈도우에선 돌아가는 코드가 리눅스에서 안 돌아가고 있습니다.

이유를 찾아봤더니, 아래와 같은 assert 에러인데...

assert(val>=0.0f);

-0.02 * 50 + 1.00 이 값이 윈도우에선 0으로 나오는데,

(위에서 -0.02 는 1/50의 결과입니다. 이것도 영향이 있을듯)

리눅스에선

-0.00000000000000002082 로 나오네요.

(0이 소숫점 아래 16개..)

precision 문제인 것 같은데, cpp에서 보면 setprecision 같은 함수의 경우는 cout 과 같이 쓰여서 출력시의 자릿수를 고치는 것 같은데, 이건 아닌 거 같고...

위 같은 경우 소숫점 14자리 정도만 정밀도를 보고 비교하도록 고치는 방법이 없을까요?

precision을 소숫점 14자리 정도로 바꾸고 싶은데, 좋은 방법이 없을지...

답변에 미리 감사드립니다.

doldori의 이미지

tolerance를 주면 되지 않을까요?

const double tolerance = 1.e-14;
assert(abs(val) >= tolerance);
ssehoony의 이미지

부동소수의 계산은 모든 cpp 컴파일러가 동일한 로직으로 처리한는게 아니였나요?
예전에 제가 테스트 했을 때는 오차나 결과 등등이 모두
gcc 와 ms 컴파일러가 동일했던 걸로 기억하는데...

lifthrasiir의 이미지

일단 실용적인 방법으로는 doldori 님의 코드처럼 tolerance가 가장 좋은 방법입니다. 실수 값은 믿기가 힘들어서 말이죠 :)

그리고 대충 컴파일 결과를 디스어셈블해서 보니까 리눅스(objdump -d 사용)와 윈도우(-ㅅ-)에서 같은 어셈블리 코드가 나오는 것 같습니다. 하지만 출력 결과는 살짝 다르더군요. 다음은 위에서 말씀하신 -0.02 * 50 + 1.00을 한 단계씩 계산한 결과입니다.

리눅스: (GCC 3.3.5)
-0.0200000000000000004163336    7B 14 AE 47 E1 7A 94 BF
-1.0000000000000000000000000    00 00 00 00 00 00 F0 BF
0.0000000000000000000000000     00 00 00 00 00 00 00 00

윈도우: (MSVC++ 6)
-0.0200000000000000000000000    7B 14 AE 47 E1 7A 94 BF
-1.0000000000000000000000000    00 00 00 00 00 00 F0 BF
0.0000000000000000000000000     00 00 00 00 00 00 00 00

왼쪽은 printf("%.25lf", number);로 출력되는 숫자이고 오른쪽은 그 바이트 표현입니다. 즉, 다른 계산 결과가 나온 게 아니라 애초에 printf의 출력 방법이 달라서 저런 결과가 나온다는 걸 알 수 있습니다. (아마 위에서 말씀하신 것도 이런 이유 때문인 것 같습니다.)

아래는 제가 사용한 테스트 코드입니다.

#include <stdio.h>

void print(double a) {
    int i;
    printf("%.25lf\t", a);
    for(i=0; i<sizeof(a); i++) {
        printf("%02hhX ", *(i+(char*)&a) & 0xff);
    }
    printf("\n");
}

int main() {
    double a;
    a = -0.02; print(a);
    a *= 50; print(a);
    a += 1.00; print(a);
    return 0;
}

- 토끼군

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.