したがって、単純な浮動小数点丸め関数が必要です。
double round(double);
round(0.1) = 0
round(-0.1) = 0
round(-0.9) = -1
math.h でceil()
とを見つけることができますが、 ではありません。floor()
round()
別の名前で標準 C++ ライブラリに存在しますか、それとも欠落していますか??
したがって、単純な浮動小数点丸め関数が必要です。
double round(double);
round(0.1) = 0
round(-0.1) = 0
round(-0.9) = -1
math.h でceil()
とを見つけることができますが、 ではありません。floor()
round()
別の名前で標準 C++ ライブラリに存在しますか、それとも欠落していますか??
編集者注:次の回答は、いくつかの実装上の欠陥を含む単純なソリューションを提供します (完全な説明については、 Shafik Yaghmour の回答を参照してください)。C++11 には
std::round
、std::lround
、 、およびstd::llround
がビルトインとして既に含まれていることに注意してください。
C++98 標準ライブラリには round() はありません。ただし、自分で書くこともできます。以下はround-half-upの実装です。
double round(double d)
{
return floor(d + 0.5);
}
C++98 標準ライブラリにラウンド関数がない理由として考えられるのは、実際にはさまざまな方法で実装できるためです。上記は一般的な方法の 1 つですが、round-to-evenなどの他の方法もあります。これは偏りが少なく、多くの丸めを行う場合に一般的に優れています。ただし、実装はもう少し複雑です。
Boost は、単純な丸め関数のセットを提供します。
#include <boost/math/special_functions/round.hpp>
double a = boost::math::round(1.5); // Yields 2.0
int b = boost::math::iround(1.5); // Yields 2 as an integer
詳細については、Boost のドキュメントを参照してください。
編集:C++11以降、、、およびがstd::round
ありstd::lround
ますstd::llround
。
C++03 標準は、標準が C++03 標準の草案 (C++03に最も近い公開されている草案標準は N1804 です)セクションでカバーされている標準 C ライブラリと呼ぶものについて、C90 標準に依存しています。1.2
ISO/IEC 9899:1990 の第 7 節および ISO/IEC 9899/Amd.1:1995 の第 7 節に記載されているライブラリを、以降、標準 C ライブラリと呼びます。1)
cppreference の round、lround、llroundのC ドキュメントにアクセスすると、 roundおよび関連する関数はC99の一部であるため、C++03 以前では使用できないことがわかります。
C++11 では、C++11 がC 標準ライブラリの C99 ドラフト標準に依存しているため、これが変更され、したがってstd::round が提供され、整数型の戻り値の型 std::lround、std::llround が提供されます。
#include <iostream>
#include <cmath>
int main()
{
std::cout << std::round( 0.4 ) << " " << std::lround( 0.4 ) << " " << std::llround( 0.4 ) << std::endl ;
std::cout << std::round( 0.5 ) << " " << std::lround( 0.5 ) << " " << std::llround( 0.5 ) << std::endl ;
std::cout << std::round( 0.6 ) << " " << std::lround( 0.6 ) << " " << std::llround( 0.6 ) << std::endl ;
}
C99 からの別のオプションはstd::truncです。
大きさが arg より大きくない最も近い整数を計算します。
#include <iostream>
#include <cmath>
int main()
{
std::cout << std::trunc( 0.4 ) << std::endl ;
std::cout << std::trunc( 0.9 ) << std::endl ;
std::cout << std::trunc( 1.1 ) << std::endl ;
}
C++11 以外のアプリケーションをサポートする必要がある場合は、boost round、iround、lround、llround、またはboost truncを使用することをお勧めします。
独自のバージョンのラウンドを展開するのは難しい
見た目より難しい: 浮動小数点数を最も近い整数に丸める (パート 1 ) 、浮動小数点数を最も近い整数に丸める(パート 2) 、浮動小数点数を最も近い整数に丸める (パート 3)説明:
たとえば、実装を使用std::floor
および追加する一般的なロール0.5
は、すべての入力に対して機能しません。
double myround(double d)
{
return std::floor(d + 0.5);
}
これが失敗する 1 つの入力は0.49999999999999994
, です (ライブで参照してください)。
別の一般的な実装には、浮動小数点型を整数型にキャストすることが含まれます。これは、整数部分を宛先の型で表現できない場合に未定義の動作を引き起こす可能性があります。これは、ドラフト C++ 標準セクション4.9
Floating-integral conversionsから見ることができます(私の強調):
浮動小数点型の prvalue は、整数型の prvalue に変換できます。変換は切り捨てられます。つまり、小数部分は破棄されます。切り捨てられた値を変換先の型で表すことができない場合、動作は未定義です。[...]
例えば:
float myround(float f)
{
return static_cast<float>( static_cast<unsigned int>( f ) ) ;
}
次に、次の呼び出しstd::numeric_limits<unsigned int>::max()
が与えられます。4294967295
myround( 4294967296.5f )
オーバーフローが発生します(ライブでご覧ください)。
Concise way to implement round() in C?に対するこの回答を見ると、これが実際にどれほど難しいかがわかります。単精度浮動小数点ラウンドのnewlibsバージョンを参照しています。単純に見えるものの非常に長い関数です。浮動小数点の実装に関する詳しい知識がなければ、この関数を正しく実装できるとは思えません。
float roundf(x)
{
int signbit;
__uint32_t w;
/* Most significant word, least significant word. */
int exponent_less_127;
GET_FLOAT_WORD(w, x);
/* Extract sign bit. */
signbit = w & 0x80000000;
/* Extract exponent field. */
exponent_less_127 = (int)((w & 0x7f800000) >> 23) - 127;
if (exponent_less_127 < 23)
{
if (exponent_less_127 < 0)
{
w &= 0x80000000;
if (exponent_less_127 == -1)
/* Result is +1.0 or -1.0. */
w |= ((__uint32_t)127 << 23);
}
else
{
unsigned int exponent_mask = 0x007fffff >> exponent_less_127;
if ((w & exponent_mask) == 0)
/* x has an integral value. */
return x;
w += 0x00400000 >> exponent_less_127;
w &= ~exponent_mask;
}
}
else
{
if (exponent_less_127 == 128)
/* x is NaN or infinite. */
return x + x;
else
return x;
}
SET_FLOAT_WORD(x, w);
return x;
}
一方、他のソリューションが使用できない場合、十分にテストされた実装であるため、 newlibがオプションになる可能性があります。
丸めから整数の結果が必要な場合は、ceil または floor を介して渡す必要がないことに注意してください。すなわち、
int round_int( double r ) {
return (r > 0.0) ? (r + 0.5) : (r - 0.5);
}
cmath の C++11 以降で利用可能です ( http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdfによると) 。
#include <cmath>
#include <iostream>
int main(int argc, char** argv) {
std::cout << "round(0.5):\t" << round(0.5) << std::endl;
std::cout << "round(-0.5):\t" << round(-0.5) << std::endl;
std::cout << "round(1.4):\t" << round(1.4) << std::endl;
std::cout << "round(-1.4):\t" << round(-1.4) << std::endl;
std::cout << "round(1.6):\t" << round(1.6) << std::endl;
std::cout << "round(-1.6):\t" << round(-1.6) << std::endl;
return 0;
}
出力:
round(0.5): 1
round(-0.5): -1
round(1.4): 1
round(-1.4): -1
round(1.6): 2
round(-1.6): -2
通常は として実装されfloor(value + 0.5)
ます。
編集: そして、私が知っている少なくとも 3 つの丸めアルゴリズムがあるため、おそらく round とは呼ばれません: ゼロへの丸め、最も近い整数への丸め、およびバンカーの丸め。最も近い整数への丸めを求めています。
私たちが見ている2つの問題があります:
丸め変換とは、± float/double を最も近い floor/ceil float/double に丸めることを意味します。あなたの問題はここで終わるかもしれません。ただし、Int/Long を返すことが期待される場合は、型変換を実行する必要があるため、「オーバーフロー」の問題が解決策に影響を与える可能性があります。SO、関数のエラーをチェックしてください
long round(double x) {
assert(x >= LONG_MIN-0.5);
assert(x <= LONG_MAX+0.5);
if (x >= 0)
return (long) (x+0.5);
return (long) (x-0.5);
}
#define round(x) ((x) < LONG_MIN-0.5 || (x) > LONG_MAX+0.5 ?\
error() : ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
Boost では、特定の種類の丸めも実装されています。
#include <iostream>
#include <boost/numeric/conversion/converter.hpp>
template<typename T, typename S> T round2(const S& x) {
typedef boost::numeric::conversion_traits<T, S> Traits;
typedef boost::numeric::def_overflow_handler OverflowHandler;
typedef boost::numeric::RoundEven<typename Traits::source_type> Rounder;
typedef boost::numeric::converter<T, S, Traits, OverflowHandler, Rounder> Converter;
return Converter::convert(x);
}
int main() {
std::cout << round2<int, double>(0.1) << ' ' << round2<int, double>(-0.1) << ' ' << round2<int, double>(-0.9) << std::endl;
}
これは、整数への変換を行う場合にのみ機能することに注意してください。
最近では、C99/C++11 数学ライブラリを含む C++11 コンパイラを使用しても問題ありません。しかし、問題は次のようになります。どの丸め関数を選択しますか?
C99/C++11round()
は、実際には必要な丸め関数ではないことがよくあります。中途半端な場合のタイブレークとして、0 から離れて丸めるファンキーな丸めモードを使用します ( +-xxx.5000
)。その丸めモードが特に必要な場合、またはround()
より高速なC++ 実装をターゲットにしている場合はrint()
、それを使用します (または、この質問に対する他の回答の 1 つを使用してその動作をエミュレートします。丸め動作。)
round()
の丸めは、IEEE754 のデフォルトの丸めとは異なり、タイブレークとしても使用されます。Nearest-even は、数値の平均の大きさにおける統計的偏りを回避しますが、偶数に向かって偏ります。
現在のデフォルトの丸めモードを使用する 2 つの数学ライブラリの丸め関数がstd::nearbyint()
ありstd::rint()
ますstd::round()
。唯一の違いは、nearbyint
FE_INEXACT が発生しないことです。
rint()
パフォーマンス上の理由から優先: gcc と clang はどちらもインライン化が容易ですが、gcc はインライン化されませんnearbyint()
( を使用しても-ffast-math
) 。
Matt Godbolt の Compiler Explorerにいくつかのテスト関数を配置しました。ここでは、source + asm 出力 (複数のコンパイラの場合) を確認できます。コンパイラ出力の読み取りの詳細については、この Q&Aと Matt の CppCon2017 トークを参照してください。コンパイラのふたを外す」</a>,
FP コードでは、通常、小さな関数をインライン化することは大きなメリットです。特に Windows 以外では、標準の呼び出し規約に呼び出し保存レジスタがないため、コンパイラはcall
. したがって、asm をよく知らなくても、それがライブラリ関数の末尾呼び出しに過ぎないのか、それとも 1 つまたは 2 つの数学命令にインライン化されているのかを簡単に確認できます。1 つまたは 2 つの命令にインライン化するものは、関数呼び出しよりも優れています (x86 または ARM でのこの特定のタスクの場合)。
x86 では、SSE4.1 にインライン化されたものroundsd
roundpd
はすべて SSE4.1 (または AVX )で自動ベクトル化できvroundpd
ます。(FP->整数変換は、AVX512 を必要とする FP->64 ビット整数を除いて、パックされた SIMD 形式でも利用できます。)
std::nearbyint()
:
-msse4.1
ます。-msse4.1 -ffast-math
gcc 5.4以前でのみ。後のgccはそれをインライン化することはありません(おそらく、即値ビットの1つが不正確な例外を抑制できることに気付いていなかったのでしょうか?それはclangが使用するものですが、古いgccrint
はインライン化するときと同じ即値を使用します)std::rint
:
-msse4.1
-msse4.1
ます。(SSE4.1 を使用しない場合、複数の命令にインライン化されます)-ffast-math -msse4.1
.std::round
:
-ffast-math -msse4.1
。2 つのベクトル定数が必要です。std::floor
/ std::ceil
/std::trunc
-msse4.1
-msse4.1
-ffast-math -msse4.1
int
/ long
/への丸めlong long
:ここには 2 つのオプションがあります: 使用するlrint
(rint
ただし、 return long
、またはlong long
for のようにllrint
)、または FP->FP 丸め関数を使用してから、通常の方法で (切り捨てを使用して) 整数型に変換します。一部のコンパイラは、ある方法を他の方法よりも最適化します。
long l = lrint(x);
int i = (int)rint(x);
or ->を最初にint i = lrint(x)
変換してから、整数を に切り捨てることに注意してください。これは、範囲外の整数に違いをもたらします: C++ では未定義の動作ですが、x86 FP -> int 命令については明確に定義されています (定数の伝播を実行しているときにコンパイル時に UB が検出されない限り、コンパイラは発行します。実行された場合に壊れるコードを作成することが許可されています)。float
double
long
int
x86 では、整数をオーバーフローする FP->integer 変換により、INT_MIN
or (符号ビットが設定された 64 ビット相当のビットLLONG_MIN
パターン) が生成されます。0x8000000
Intel では、これを「整数不定」値と呼んでいます。(マニュアル エントリを参照してcvttsd2si
ください。これは、スカラー double を符号付き整数に変換する SSE2 命令です (切り捨てあり)。32 ビットまたは 64 ビット整数の変換先で使用できます (64 ビット モードのみ)。cvtsd2si
(convert with current rounding ) もあります。これはコンパイラに出力させたいものですが、残念ながら gcc と clang は-ffast-math
.
またunsigned
、x86 (AVX512 なし) では int / long との間の FP の効率が悪いことに注意してください。64 ビット マシンでの 32 ビット符号なしへの変換はかなり安価です。64 ビットの符号付きに変換して切り捨てるだけです。しかし、それ以外の場合は大幅に遅くなります。
x86 clang with/without -ffast-math -msse4.1
: (int/long)rint
inlines to roundsd
/ cvttsd2si
. ( への最適化を逃したcvtsd2si
)。 lrint
まったくインライン化されません。
x86 gcc6.x 以前なし-ffast-math
: どちらの方法もインライン化されていません
-ffast-math
:丸め、個別に変換します (SSE4.1 の合計 2 つの命令が有効になっている場合、そうでない場合はwithout(int/long)rint
のインライン化された一連のコードがあります)。 インライン化されません。rint
roundsd
lrint
x86 gcc with -ffast-math
: (optimal)にすべてインラインcvtsd2si
化、SSE4.1 は不要。
なしの AArch64 gcc6.3 -ffast-math
: (int/long)rint
2 つの命令にインライン化します。 lrint
インライン化しない
-ffast-math
:(int/long)rint
への呼び出しにコンパイルされlrint
ます。 lrint
インライン化されません。これは、得られない 2 つの命令-ffast-math
が非常に遅い場合を除き、最適化の失敗である可能性があります。次のようにして、n桁の精度に丸めることができます。
double round( double x )
{
const double sd = 1000; //for accuracy to 3 decimal places
return int(x*sd + (x<0? -0.5 : 0.5))/sd;
}
最終的に関数のdouble
出力をに変換したい場合、この質問の受け入れられる解決策は次のようになります。round()
int
int roundint(double r) {
return (int)((r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5));
}
これは、一様にランダムな値が渡されると、私のマシンでは約8.88 nsで記録されます。
私が知る限り、以下は機能的に同等ですが、私のマシンでは2.48 nsで動作し、パフォーマンスが大幅に向上します。
int roundint (double r) {
int tmp = static_cast<int> (r);
tmp += (r-tmp>=.5) - (r-tmp<=-.5);
return tmp;
}
パフォーマンスが向上する理由の 1 つに、分岐のスキップがあります。
注意してくださいfloor(x+0.5)
。[2 ^ 52,2^53]の範囲の奇数で発生する可能性があるのは次のとおりです。
-bash-3.2$ cat >test-round.c <<END
#include <math.h>
#include <stdio.h>
int main() {
double x=5000000000000001.0;
double y=round(x);
double z=floor(x+0.5);
printf(" x =%f\n",x);
printf("round(x) =%f\n",y);
printf("floor(x+0.5)=%f\n",z);
return 0;
}
END
-bash-3.2$ gcc test-round.c
-bash-3.2$ ./a.out
x =5000000000000001.000000
round(x) =5000000000000001.000000
floor(x+0.5)=5000000000000002.000000
これはhttp://bugs.squeak.org/view.php?id=7134です。@konikのようなソリューションを使用してください。
私自身の堅牢なバージョンは次のようになります。
double round(double x)
{
double truncated,roundedFraction;
double fraction = modf(x, &truncated);
modf(2.0*fraction, &roundedFraction);
return truncated + roundedFraction;
}
floor(x + 0.5)を避けるもう1つの理由は、ここに示されています。
関数double round(double)
を使用したmodf
関数:
double round(double x)
{
using namespace std;
if ((numeric_limits<double>::max() - 0.5) <= x)
return numeric_limits<double>::max();
if ((-1*std::numeric_limits<double>::max() + 0.5) > x)
return (-1*std::numeric_limits<double>::max());
double intpart;
double fractpart = modf(x, &intpart);
if (fractpart >= 0.5)
return (intpart + 1);
else if (fractpart >= -0.5)
return intpart;
else
return (intpart - 1);
}
クリーンにコンパイルするには、"math.h" と "limits" を含める必要があります。この関数は、次の丸めスキーマに従って機能します。
Kalaxy の応答に基づいて、自然な丸めに基づいて任意の浮動小数点数を最も近い整数型に丸めるテンプレート化されたソリューションを次に示します。また、値が整数型の範囲外の場合、デバッグ モードでエラーをスローするため、ほぼ実行可能なライブラリ関数として機能します。
// round a floating point number to the nearest integer
template <typename Arg>
int Round(Arg arg)
{
#ifndef NDEBUG
// check that the argument can be rounded given the return type:
if (
(Arg)std::numeric_limits<int>::max() < arg + (Arg) 0.5) ||
(Arg)std::numeric_limits<int>::lowest() > arg - (Arg) 0.5)
)
{
throw std::overflow_error("out of bounds");
}
#endif
return (arg > (Arg) 0.0) ? (int)(r + (Arg) 0.5) : (int)(r - (Arg) 0.5);
}
コメントやその他の回答で指摘されているように、ISO C++ 標準ライブラリはround()
、この関数が ISO C99 標準数学ライブラリへの参照によって取り込まれた ISO C++11 まで追加されませんでした。
[½, ub ]の正のオペランドのround(x) == floor (x + 0.5)
場合、ここで、ubは、IEEE-754 (2008) にマップされる場合は 2 23であり、IEEE-754 (2008) にマップされる場合は 2 52です。数値 23 と 52 は、これら 2 つの浮動小数点形式で格納された仮数ビットの数に対応します。[+0, ½)の正のオペランド、および ( ub , +∞]の正のオペランドの場合. 関数は x 軸に対して対称であるため、負の引数は に従って処理できます。float
binary32
double
binary64
round(x) == 0
round(x) == x
x
round(-x) == -round(x)
これにより、以下のコンパクトなコードが得られます。さまざまなプラットフォームで妥当な数の機械語命令にコンパイルされます。私は GPU で最もコンパクトなコードを観察しました。ここでmy_roundf()
は、約 12 個の命令が必要です。プロセッサのアーキテクチャとツールチェーンに応じて、この浮動小数点ベースのアプローチは、別の回答で参照されている newlib の整数ベースの実装よりも高速または低速になる可能性があります。
インテル® コンパイラーのバージョン 13 を使用my_roundf()
して、newlib の実装を徹底的にテストしました。また、newlib のバージョンが Intel コンパイラのライブラリと一致することも確認しました。倍精度の完全なテストはできませんが、コードは構造的に単精度の実装と同じです。roundf()
/fp:strict
/fp:fast
roundf()
mathimf
round()
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
float my_roundf (float x)
{
const float half = 0.5f;
const float one = 2 * half;
const float lbound = half;
const float ubound = 1L << 23;
float a, f, r, s, t;
s = (x < 0) ? (-one) : one;
a = x * s;
t = (a < lbound) ? x : s;
f = (a < lbound) ? 0 : floorf (a + half);
r = (a > ubound) ? x : (t * f);
return r;
}
double my_round (double x)
{
const double half = 0.5;
const double one = 2 * half;
const double lbound = half;
const double ubound = 1ULL << 52;
double a, f, r, s, t;
s = (x < 0) ? (-one) : one;
a = x * s;
t = (a < lbound) ? x : s;
f = (a < lbound) ? 0 : floor (a + half);
r = (a > ubound) ? x : (t * f);
return r;
}
uint32_t float_as_uint (float a)
{
uint32_t r;
memcpy (&r, &a, sizeof(r));
return r;
}
float uint_as_float (uint32_t a)
{
float r;
memcpy (&r, &a, sizeof(r));
return r;
}
float newlib_roundf (float x)
{
uint32_t w;
int exponent_less_127;
w = float_as_uint(x);
/* Extract exponent field. */
exponent_less_127 = (int)((w & 0x7f800000) >> 23) - 127;
if (exponent_less_127 < 23) {
if (exponent_less_127 < 0) {
/* Extract sign bit. */
w &= 0x80000000;
if (exponent_less_127 == -1) {
/* Result is +1.0 or -1.0. */
w |= ((uint32_t)127 << 23);
}
} else {
uint32_t exponent_mask = 0x007fffff >> exponent_less_127;
if ((w & exponent_mask) == 0) {
/* x has an integral value. */
return x;
}
w += 0x00400000 >> exponent_less_127;
w &= ~exponent_mask;
}
} else {
if (exponent_less_127 == 128) {
/* x is NaN or infinite so raise FE_INVALID by adding */
return x + x;
} else {
return x;
}
}
x = uint_as_float (w);
return x;
}
int main (void)
{
uint32_t argi, resi, refi;
float arg, res, ref;
argi = 0;
do {
arg = uint_as_float (argi);
ref = newlib_roundf (arg);
res = my_roundf (arg);
resi = float_as_uint (res);
refi = float_as_uint (ref);
if (resi != refi) { // check for identical bit pattern
printf ("!!!! arg=%08x res=%08x ref=%08x\n", argi, resi, refi);
return EXIT_FAILURE;
}
argi++;
} while (argi);
return EXIT_SUCCESS;
}
x86 アーキテクチャおよび MS VS 固有の C++ の asm で、次の round の実装を使用します。
__forceinline int Round(const double v)
{
int r;
__asm
{
FLD v
FISTP r
FWAIT
};
return r;
}
UPD: double 値を返す
__forceinline double dround(const double v)
{
double r;
__asm
{
FLD v
FRNDINT
FSTP r
FWAIT
};
return r;
}
出力:
dround(0.1): 0.000000000000000
dround(-0.1): -0.000000000000000
dround(0.9): 1.000000000000000
dround(-0.9): -1.000000000000000
dround(1.1): 1.000000000000000
dround(-1.1): -1.000000000000000
dround(0.49999999999999994): 0.000000000000000
dround(-0.49999999999999994): -0.000000000000000
dround(0.5): 0.000000000000000
dround(-0.5): -0.000000000000000
数学を使用する ARM の round_f
static inline float round_f(float value)
{
float rep;
asm volatile ("vrinta.f32 %0,%1" : "=t"(rep) : "t"(value));
return rep;
}
数学なしの ARM の round_f
union f__raw {
struct {
uint32_t massa :23;
uint32_t order :8;
uint32_t sign :1;
};
int32_t i_raw;
float f_raw;
};
float round_f(float value)
{
union f__raw raw;
int32_t exx;
uint32_t ex_mask;
raw.f_raw = value;
exx = raw.order - 126;
if (exx < 0) {
raw.i_raw &= 0x80000000;
} else if (exx < 24) {
ex_mask = 0x00ffffff >> exx;
raw.i_raw += 0x00800000 >> exx;
if (exx == 0) ex_mask >>= 1;
raw.i_raw &= ~ex_mask;
};
return raw.f_raw;
};
// Convert the float to a string
// We might use stringstream, but it looks like it truncates the float to only
//5 decimal points (maybe that's what you want anyway =P)
float MyFloat = 5.11133333311111333;
float NewConvertedFloat = 0.0;
string FirstString = " ";
string SecondString = " ";
stringstream ss (stringstream::in | stringstream::out);
ss << MyFloat;
FirstString = ss.str();
// Take out how ever many decimal places you want
// (this is a string it includes the point)
SecondString = FirstString.substr(0,5);
//whatever precision decimal place you want
// Convert it back to a float
stringstream(SecondString) >> NewConvertedFloat;
cout << NewConvertedFloat;
system("pause");
それは変換の非効率的な汚い方法かもしれませんが、まあ、うまくいきます笑。実際のフロートに適用されるので、それは良いことです。視覚的に出力に影響を与えるだけではありません。
これは私がしました:
#include <cmath.h>
using namespace std;
double roundh(double number, int place){
/* place = decimal point. Putting in 0 will make it round to whole
number. putting in 1 will round to the
tenths digit.
*/
number *= 10^place;
int istack = (int)floor(number);
int out = number-istack;
if (out < 0.5){
floor(number);
number /= 10^place;
return number;
}
if (out > 0.4) {
ceil(number);
number /= 10^place;
return number;
}
}