부동값을 C의 소수점 이후 두 자리까지만 제한하려면 어떻게 해야 합니까?
플로트 값(37.7779)을 C의 소수점 2자리(37.78)로 반올림하려면 어떻게 해야 합니까?
를 반올림하는 는, 「」를 해 주세요."%.2f"
형식 문자열이 정답입니다.수행할 수 있습니다.
#include <math.h>
float val = 37.777779;
float rounded_down = floorf(val * 100) / 100; /* Result: 37.77 */
float nearest = roundf(val * 100) / 100; /* Result: 37.78 */
float rounded_up = ceilf(val * 100) / 100; /* Result: 37.78 */
선택할 수 있는 반올림 규칙에는 반올림(소수점 두 자리 이후 잘라내기), 반올림 및 반올림 세 가지가 있습니다.보통은 가장 가까운 곳으로 동그랗게 오릅니다.
몇몇 다른 사람들이 지적했듯이 부동소수점 표현의 기이한 점 때문에 반올림된 이러한 값은 정확히 "명확한" 소수점 값은 아닐 수 있지만 매우 근접합니다.
반올림에 대한 자세한 정보, 특히 가장 가까운 반올림에 대한 동점 처리 규칙에 대한 자세한 내용은 반올림 관련 위키피디아 문서를 참조하십시오.
printf에서 %.2f를 사용합니다.소수점 2개만 출력됩니다.
예를 들어:
printf("%.2f", 37.777779);
출력:
37.77
「」를 해 주세요.printf
능능패패 패다다다다다플로트로서 가치를 얻고 싶어도, 이 기능을 사용하는 것이 가장 좋습니다.snprintf
후 atof
:
#include <math.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
double dround(double val, int dp) {
int charsNeeded = 1 + snprintf(NULL, 0, "%.*f", dp, val);
char *buffer = malloc(charsNeeded);
snprintf(buffer, charsNeeded, "%.*f", dp, val);
double result = atof(buffer);
free(buffer);
return result;
}
제가 이렇게 말하는 이유는 현재 가장 많이 투표된 답변과 다른 답변에서 보여지는 접근법(100을 곱하고, 가장 가까운 정수로 반올림하고, 다시 100으로 나누는 방법)에 두 가지 면에서 결함이 있기 때문입니다.
- 일부 값에서는 부동 소수점 숫자의 부정확성으로 인해 100을 곱하면 반올림 방향을 결정하는 소수 자릿수가 4에서 5로 변경되거나 그 반대로 변경되기 때문에 잘못된 방향으로 반올림됩니다.
- 일부 값에서는 곱한 후 100으로 나누면 라운드 트립이 되지 않습니다. 즉, 반올림이 이루어지지 않더라도 최종 결과가 잘못됩니다.
첫 번째 오류(반올림 방향이 잘못될 수 있음)를 설명하려면 이 프로그램을 실행하십시오.
int main(void) {
// This number is EXACTLY representable as a double
double x = 0.01499999999999999944488848768742172978818416595458984375;
printf("x: %.50f\n", x);
double res1 = dround(x, 2);
double res2 = round(100 * x) / 100;
printf("Rounded with snprintf: %.50f\n", res1);
printf("Rounded with round, then divided: %.50f\n", res2);
}
다음의 출력이 표시됩니다.
x: 0.01499999999999999944488848768742172978818416595459
Rounded with snprintf: 0.01000000000000000020816681711721685132943093776703
Rounded with round, then divided: 0.02000000000000000041633363423443370265886187553406
여기서 시작한 값은 0.015보다 작기 때문에 소수점 2자리로 반올림했을 때의 수학 정답은 0.01입니다.물론 0.01이 배수로 정확하게 표현되는 것은 아니지만, 0.01에 가장 가까운 배수가 될 것으로 예상됩니다.사용.snprintf
수 , '이러다'를 round(100 * x) / 100
요? 0.02예요? ★★★★★★★★★★★★★★★★★★100 * x
1.5로 하다따라서 100을 곱하면 올바른 반올림 방향이 변경됩니다.
두 번째 유형의 오류를 설명하기 위해 다음과 같은 이유로 인해 결과가 잘못될 수 있습니다.* 100
★★★★★★★★★★★★★★★★★」/ 100
실제로 서로를 역행하는 것이 아니라 매우 큰 수로 비슷한 운동을 할 수 있다.
int main(void) {
double x = 8631192423766613.0;
printf("x: %.1f\n", x);
double res1 = dround(x, 2);
double res2 = round(100 * x) / 100;
printf("Rounded with snprintf: %.1f\n", res1);
printf("Rounded with round, then divided: %.1f\n", res2);
}
는 이제, '정수값'으로 되어 있어요.double
반올림 후 결과는 처음과 같은 숫자여야 하는 거 맞죠?
위의 프로그램을 실행하면 다음과 같이 표시됩니다.
x: 8631192423766613.0
Rounded with snprintf: 8631192423766613.0
Rounded with round, then divided: 8631192423766612.0
우리 아, 아, 아.snprintf
다시 실패합니다.method는 multiply-the-round-then-the-then-then-then-then-then-then-divide의 수학적으로 올바른 을 반환하기 8631192423766613.0 * 100
,863119242376661300.0
수 것은 가까운 값은 「」, 「2」, 「2」입니다.가장 가까운 값은863119242376661248.0
이 됩니다8631192423766612.0
- 번호입니다.
정도면 충분히 할 수 있을 입니다.roundf
반올림을 할 수 .snprintf
대신.만약 그것이 당신에게 끔찍한 해킹으로 느껴진다면, 아마도 당신은 그것이 기본적으로 CPython이 하는 일이라는 것을 알면 안심할 수 있을 것이다.
C++(또는 C-스타일 캐스팅이 있는 C)에서 다음 함수를 만들 수 있습니다.
/* Function to control # of decimal places to be output for x */
double showDecimals(const double& x, const int& numDecimals) {
int y=x;
double z=x-y;
double m=pow(10,numDecimals);
double q=z*m;
double r=round(q);
return static_cast<double>(y)+(1.0/m)*r;
}
★★★★★★★★★★★★★★★.std::cout << showDecimals(37.777779,2);
37.78을 생성합니다.
물론 이 함수에 5가지 변수를 모두 만들 필요는 없지만 논리를 볼 수 있도록 그대로 둡니다.간단한 해결 방법이 있을 수 있지만, 특히 필요에 따라 소수점 이후의 자리수를 조정할 수 있기 때문에 이 방법은 효과적입니다.
Andrew Coleson과 AraK의 답변은 인쇄의 가치를 반올림한다고 가정하면 다음과 같습니다.
printf("%.2f", 37.777779);
단, 내부 사용(예를 들어 다른 값과 비교)을 위해 정확히 37.78로 반올림하려는 경우에는 부동소수점 숫자가 작동하는 방식으로 인해 이는 좋은 생각이 아닙니다. 일반적으로 부동소수점 값을 동등하게 비교하는 것은 원치 않습니다. 대신 목표값 +/- 시그마 값을 사용하십시오.또는 숫자를 알려진 정밀도의 문자열로 인코딩하여 비교합니다.
관련 질문에 대한 Greg Hewgill의 답변 링크를 참조하십시오. 이 링크에서는 재무 계산에 부동 소수점을 사용하지 않는 이유도 다룹니다.
또, C++ 를 사용하고 있는 경우는, 다음과 같은 함수를 작성할 수 있습니다.
string prd(const double x, const int decDigits) {
stringstream ss;
ss << fixed;
ss.precision(decDigits); // set # places after decimal
ss << x;
return ss.str();
}
임의의 할 수 있습니다.myDouble
n
다음과 같은 코드를 가진 소수점 뒤의 자리:
std::cout << prd(myDouble,n);
코드 정의:
#define roundz(x,d) ((floor(((x)*pow(10,d))+.5))/pow(10,d))
결과:
a = 8.000000
sqrt(a) = r = 2.828427
roundz(r,2) = 2.830000
roundz(r,3) = 2.828000
roundz(r,5) = 2.828430
다음 항목을 사용할 수 있습니다.
float ceilf(float x); // don't forget #include <math.h> and link with -lm.
예:
float valueToRound = 37.777779;
float roundedValue = ceilf(valueToRound * 100) / 100;
이거 어때:
float value = 37.777779;
float rounded = ((int)(value * 100 + .5) / 100.0);
printf("%.2f", 37.777779);
C 문자열에 쓰는 경우:
char number[24]; // dummy size, you should take care of the size!
sprintf(number, "%.2f", 37.777779);
먼저 이 질문에 대한 또 다른 답을 덧붙이는 이유를 설명하겠습니다.이상적인 세계에서는 라운딩이 그다지 큰 문제가 되지 않습니다.그러나 실제 시스템에서는 예상과 다른 반올림 결과를 초래할 수 있는 몇 가지 문제에 대처해야 할 수 있습니다.예를 들어 최종 결과가 소수점 2자리 숫자로 반올림되어 사용자에게 표시되는 재무 계산을 수행할 수 있습니다.이러한 값은 소수점 2자리보다 많은 데이터베이스에 고정 정밀하게 저장됩니다(다양한 이유로 최적의 장소 수가 없습니다). 각 시스템의 특정 상황에 따라 달라집니다.스템은 예를 들어 가격이 단위당 1페니의 일부인 작은 항목과 결과가 엡실론 플러스/플러스인 값에 대해 수행된 부동 소수점 계산을 지원해야 한다.나는 수년간 이러한 문제에 직면하여 나 자신의 전략을 발전시켜 왔다.모든 시나리오에 직면했거나 최선의 답변을 가지고 있다고는 할 수 없지만, 이러한 문제를 해결하기 위한 지금까지의 접근방식의 예를 다음에 제시하겠습니다.
소수점 6자리를 다음과 같은 반올림 함수/방법을 사용하여 부동/이중(특정 적용에 대한 임의 결정) 계산에 충분한 정밀도로 간주한다고 가정합니다.
double Round(double x, int p)
{
if (x != 0.0) {
return ((floor((fabs(x)*pow(double(10.0),p))+0.5))/pow(double(10.0),p))*(x/fabs(x));
} else {
return 0.0;
}
}
결과 표시를 위해 소수점 이하 2자리 반올림을 다음과 같이 수행할 수 있다.
double val;
// ...perform calculations on val
String(Round(Round(Round(val,8),6),2));
★★★의 val = 6.825
는 입니다.6.83
역시나
★★★의 val = 6.824999
는 입니다.6.82
계산 6.824999
소수점 7번째 자리는 0입니다.
위해서val = 6.8249999
, 결과는 다음과 같습니다.6.83
소수점 이하 일곱 번째 자리는9
이 경우,Round(val,6)
원하는 결과를 제공하는 함수입니다.이 경우, 임의의 수의 후행자가 있을 수 있습니다.9
s.
위해서val = 6.824999499999
, 결과는 다음과 같습니다.6.83
첫 번째 단계로 소수점 이하 8자리 반올림.Round(val,8)
는 계산된 부동소수점 결과가 다음과 같이 계산되는 귀찮은 경우를 처리합니다.6.8249995
단, 내부적으로는6.824999499999...
.
마지막으로 질문의 예시는...val = 37.777779
을 낳다37.78
.
이 접근방식은 다음과 같이 더욱 일반화될 수 있습니다.
double val;
// ...perform calculations on val
String(Round(Round(Round(val,N+2),N),2));
여기서 N은 플로트/더블의 모든 중간 계산에 대해 유지해야 할 정밀도이다.이것은 음의 값에도 작용합니다.나는 이 접근법이 모든 가능성에 대해 수학적으로 정확한지 모르겠다.
a를 반올림할 방법이 없다float
타인에게float
동그란 것이float
는 나타낼 수 없는 경우가 있습니다(부동소수점 숫자의 제한).예를 들어, 37.7779에서 37.78로 반올림한다고 가정합니다. 그러나 가장 가까운 대표 숫자는 37.781입니다.
단, '둥근'을 할 수 있습니다.float
형식 문자열 기능을 사용하여 지정합니다.
...또는 라이브러리 없이 구식 방식으로 작업을 수행할 수도 있습니다.
float a = 37.777779;
int b = a; // b = 37
float c = a - b; // c = 0.777779
c *= 100; // c = 77.777863
int d = c; // d = 77;
a = b + d / (float)100; // a = 37.770000;
물론 번호에서 추가 정보를 제거하고 싶다면.
플로트 숫자를 반올림하기 위해 이 매크로를 만들었습니다.헤더 또는 파일에 추가
#define ROUNDF(f, c) (((float)((int)((f) * (c))) / (c)))
다음은 예를 제시하겠습니다.
float x = ROUNDF(3.141592, 100)
x = 3.14 :)
사용하다float roundf(float x)
.
"라운드 함수는 인수를 부동소수점 형식의 가장 가까운 정수값으로 반올림하여 현재 반올림 방향에 관계없이 0에서 반올림합니다." C11dr § 7.12.9.5
#include <math.h>
float y = roundf(x * 100.0f) / 100.0f;
고객님의 요구에 따라float
실장에서는, 반쪽인 것처럼 보이는 숫자는 없습니다.플로팅 포인트는 일반적으로 베이스 2를 지향하고 있기 때문입니다.또한, 가장 가까운 부분까지 정확하게 반올림합니다.0.01
모든 "반쪽" 케이스가 가장 어려운 문제입니다.
void r100(const char *s) {
float x, y;
sscanf(s, "%f", &x);
y = round(x*100.0)/100.0;
printf("%6s %.12e %.12e\n", s, x, y);
}
int main(void) {
r100("1.115");
r100("1.125");
r100("1.135");
return 0;
}
1.115 1.115000009537e+00 1.120000004768e+00
1.125 1.125000000000e+00 1.129999995232e+00
1.135 1.134999990463e+00 1.139999985695e+00
"1.11"은 1.11과 1.12 사이의 "반쪽"이지만,float
값은 다음과 같습니다.1.115000009537...
그리고 더 이상 "반쪽"이 아니라 1.12에 가깝고 가장 가까운 곳에 반올림합니다.float
의1.120000004768...
"1.125"는 1.12와 1.13 사이의 "반쪽"으로 변환됩니다.float
이 값은 정확하게1.125
'반쪽'입니다.짝수 규칙과의 연계에 의해 1.13을 향해 반올림하고 가장 가까운 값으로 반올림합니다.float
의1.129999995232...
"1.135"는 1.13과 1.14 사이의 "반쪽"이지만 변환 시float
값은 다음과 같습니다.1.134999990463...
그리고 더 이상 "반쪽"이 아니라 1.13에 가깝고 가장 가까운 곳에 반올림합니다.float
의1.129999995232...
코드가 사용되고 있는 경우
y = roundf(x*100.0f)/100.0f;
"1.135"는 1.13과 1.14 사이의 "반쪽"이지만 변환 시float
값은 다음과 같습니다.1.134999990463...
더 이상 '반쪽'이 아니라 1.13에 가깝지만 잘못 반올림하여float
의1.139999985695...
정밀도가 더 낮기 때문에float
대.double
이 잘못된 값은 코딩 목표에 따라 올바른 값으로 간주될 수 있습니다.
double f_round(double dval, int n)
{
char l_fmtp[32], l_buf[64];
char *p_str;
sprintf (l_fmtp, "%%.%df", n);
if (dval>=0)
sprintf (l_buf, l_fmtp, dval);
else
sprintf (l_buf, l_fmtp, dval);
return ((double)strtod(l_buf, &p_str));
}
여기서n
소수점 수
예:
double d = 100.23456;
printf("%f", f_round(d, 4));// result: 100.2346
printf("%f", f_round(d, 2));// result: 100.23
이 함수는 숫자와 정밀도를 가져와서 반올림된 숫자를 반환합니다.
float roundoff(float num,int precision)
{
int temp=(int )(num*pow(10,precision));
int num1=num*pow(10,precision+1);
temp*=10;
temp+=5;
if(num1>=temp)
num1+=10;
num1/=10;
num1*=10;
num=num1/pow(10,precision+1);
return num;
}
점을 왼쪽으로 이동하고 5개 이상의 조건을 확인하여 부동 소수점 번호를 int로 변환합니다.
언급URL : https://stackoverflow.com/questions/1343890/how-do-i-restrict-a-float-value-to-only-two-places-after-the-decimal-point-in-c
'IT' 카테고리의 다른 글
집약 쿼리의 프로시저 표시 또는 저장 (0) | 2022.11.07 |
---|---|
스캐너가 next() 또는 nextFoo()를 사용한 후 nextLine()을 건너뜁니다. (0) | 2022.11.07 |
명시적 약속 구성 반대는 무엇이며 어떻게 피해야 합니까? (0) | 2022.11.07 |
개체가 특정 유형임을 주장합니다. (0) | 2022.11.07 |
Spring Boot에서 응답으로 JSON 개체를 반환하는 중 (0) | 2022.11.07 |