float형을 사용할떄

heobeom의 이미지

정수형 변수의 값을 받아서

float형으로 0.1% ~ 5%까지 나타내려고 하는데

1의 0.5%를 나타내려고 1 * 0.5 / 100을 하니까

값이 0.00499998이런식으로 변경되는데.. 이값을 0.5로 변경할 수는 없을까요??

printf를 써서 출력하는 경우가 아니라서 %0.4f이런식으로 처리할 수가 없어서..

float형에 저장된 값을 문자열로 변경하여 그대로 출력하게 하는거라 0.0049라고 출력되네요 ㅠㅠ

소수점 4자리에서 반올림하면 될 것 같아서

floor( (x)*10000 +0.5) / 10000)도 추가해봤는데 별다른 차이가 없네요 ㅠㅠ;

eclipse CDT를 이용해 코딩중이고 minGW컴파일러를 쓰고 있습니다.

yukariko의 이미지

위 문제는 부동소숫점 때문인데

소숫점 한자리만 사용할 거라면 정수형으로 처리하는건 어떤가요?

예를들어 1의 0.5%를 나타낸다 하면

1000(default) * 1 / 2(0.5) / 100 = 5 가 되는데

default 가 1000 이므로 처리해줄 땐 0.005로 나타내면 되겠죠.

heobeom의 이미지

그래서 값을 integer형으로 받아서

데이터랑 곱하기 처리를 해주고

1000으로 나눌때 형변환으로 float형에 넣어주었는데

결국은 값은 똑같이 표현이 되더군요 ㅠㅠ;

int data //1~10000
int per //0.1~5 %

float output

per *= 10 //정수형으로

data *= per //연산 실행

output = (float)data / 1000.f

이렇게 해도 data가 1이고 per가 0.5이면

output값이 0.004999998 이런식으로 나오네요 ㅠㅠ;

yukariko의 이미지

나누는것도 물론 직접처리해주어야 합니다.

5를 문자열로받으면 그 앞에 0.00를 넣어주는식으로요

yukariko의 이미지

.

yukariko의 이미지

printf만 안하면 되는거라면 sprintf 는 어떠신가요?

float t = 0.005f
char a[101];
sprintf(a,"%.4f",t);

이런식으로 처리하면 될것같습니다만

heobeom의 이미지

결국은 소수점 위아래를 각각 정수형으로 표현하여

말씀하신대로 sprintf를 통해 출력하였습니다.

float input, data;
int over_value, under_value;
char str[100u];
int len;

data = (다른코드에 저장되어 있는 값 입력)

input = (입력받음)

over_value = data * 10u;
under_value = over_value % 1000u;
over_value /= 1000u;

sprintf(str, "%d.%03d", over_value, under_value);

len = strlen(str);
while(len--)
{
if(str[len] == '.')
{
str[len] = 0;
}
if(str[len] != '0')
{
break;
}
else
{
str[len] = 0;
}

이후 str을 출력하는 변수에 넣는것으로 마무리 지었습니다.

jick의 이미지

float, double은 2진수로 표현되기 때문에 2의 거듭제곱으로 딱 나누어 떨어지는 숫자만 정확히 표현할 수 있습니다.

나머지 숫자는 정확한 표현이 안됩니다. 10으로 나눠 떨어지는 정확한 소수가 필요하다면 10의 거듭제곱을 적당히 곱해서 다 정수로 만드는 수가 있습니다.

#include <stdio.h>
 
int main(void) {
    float x = 0.005;
    printf("%.40f\n", x);
 
    double y = 0.005;
    printf("%.40f\n", y);
 
    return 0;
}
 
실행결과:
0.0049999998882412910461425781250000000000
0.0050000000000000001040834085586084256647
heobeom의 이미지

확실히 double형이면 원하는 수에 가깝게 표현되겠네요

근데 저 혼자 짜는 코드가 아니라 회사에서 짜는 거다 보니

자료형을 제 맘대로 바꾸기가 쉽지 않았네요 ㅠㅠ;

klyx의 이미지

> float형에 저장된 값을 문자열로 변경하여 그대로 출력하게 하는거라 0.0049라고 출력되네요 ㅠㅠ

0.004999... 를 0.0049로 출력한다면 그건 문자열로 변경하는 과정에 문제가 있는겁니다.
0.004999... 를 5번째자리에서 반올림하면 0.0050 이 되어야 정상이죠.
문자열로 변환하는 과정에서 반올림이라는 걸 고려하지 않으신거 아닌가요?

heobeom의 이미지

banollim(x,dig) (floor((x)*pow(10,dig)+0.5)/pow(10,dig))

이러한 매크로를 찾아보고 이용해 써봤는데 코드상에서 영향을 안미치더군요 ㅠㅠ;

klyx의 이미지

수치그자체를 반올림하는게 아니라 문자열로 바꾸는 과정에서 고려해야죠.
아무리 발악을 해도 부동소수점은 부동소수점의 한계를 그대로 끌고가는 겁니다.
아니면 많은 분들이 지적한대로 고정소수점으로 구현을 하시거나요.

gilgil의 이미지

http://www.gilgil.net/8417
상기 링크 아래 부분을 보시면 특정 숫자가 내부적으로 어떻게 저장되는지 확인할 수 있습니다.
0.5, 0.25, 0.125와 같은 숫자는 정확히 표현되는 반면에 0.1과 같은 숫자는 float로 정확히 표현할 수 없습니다.
double을 쓴다 하더라도 자리수만 더 커지게 되는 work around일 뿐입니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.