소스 파일명 : int128_example.cpp
* 수정 전의 원본 소스는 여기서 구할 수 있습니다.
컴파일하기
$ g++ -o int128_example int128_example.cpp -fexceptions -std=gnu++17 -g -fext-numeric-literals -fpermissive -lquadmath
int128 정수(128비트 부호 있는 정수) 사용하는 예제
#include <quadmath.h>
#include <stdlib.h>
#include <stdio.h>
int main ()
{
__float128 r;
int prec = 20;
int width = 46;
char buf[128];
r = 2.0q;
r = sqrtq (r);
int n = quadmath_snprintf (buf, sizeof buf, "%+-#*.20Qe", width, r);
if ((size_t) n < sizeof buf)
printf ("%s\n", buf);
/* Prints: +1.41421356237309504880e+00 */
quadmath_snprintf (buf, sizeof buf, "%Qa", r);
if ((size_t) n < sizeof buf)
printf ("%s\n", buf);
/* Prints: 0x1.6a09e667f3bcc908b2fb1366ea96p+0 */
n = quadmath_snprintf (NULL, 0, "%+-#46.*Qe", prec, r);
if (n > -1)
{
char *str = (char *) malloc (n + 1);
if (str)
{
quadmath_snprintf (str, n + 1, "%+-#46.*Qe", prec, r);
printf ("%s\n", str);
/* Prints: +1.41421356237309504880e+00 */
}
free (str);
}
return 0;
}
float128 부동소수점수(128비트 부동소수점수 ) 사용하는 예제
* 소스 파일명 : float128_example.cpp
* 수정 전의 원본 소스는 여기서
224행. 225행, 226행
//std::cout << tifu128.name() << std::endl; // On GCC, aborts (because not printable string).
//std::cout << typeid(__float128).name() << std::endl; // Aborts -
// string name cannot be output.
을 아래의 두 행으로 바꾸고
std::cout << " tifu128.name() = " << tifu128.name() << std::endl;
std::cout << " typeid(__float128).name() = " << typeid(__float128).name() << std::endl;
아래 처럼 g++ 컴파일 명령으로 컴파일하면 (경고 없이) 컴파일됩니다.
* 컴파일하기
$ g++ -o float128_example.exe float128_example.cpp -I$BOOST_PATH -fexceptions -std=gnu++17 -g -fext-numeric-literals -fpermissive -lquadmath -Wunused-variable
// Copyright John Maddock 2016
// Copyright Christopher Kormanyos 2016.
// Copyright Paul A. Bristow 2016.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// Contains Quickbook snippets as C++ comments - do not remove.
// http://gcc.gnu.org/onlinedocs/libquadmath/ GCC Quad-Precision Math Library
// https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format
// https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html#C_002b_002b-Dialect-Options GNU 3.5 Options Controlling C++ Dialect
// https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html#C-Dialect-Options 3.4 Options Controlling C Dialect
//[float128_includes_1
#include <boost/cstdfloat.hpp> // For float_64_t, float128_t. Must be first include!
//#include <boost/config.hpp>
#include <boost/multiprecision/float128.hpp>
#include <boost/math/special_functions.hpp> // For gamma function.
#include <boost/math/constants/constants.hpp> // For constants pi, e ...
#include <typeinfo> //
#include <cmath> // for pow function.
// #include <quadmath.h>
// C:\program files\gcc-6-win64\lib\gcc\x86_64-w64-mingw32\6.1.1\include\quadmath.h
// i:\modular-boost\boost\multiprecision\float128.hpp|210| undefined reference to `quadmath_snprintf'.
//] [/float128_includes_1]
//[float128_dialect_1
/*`To make float128 available it is vital to get the dialect and options on the command line correct.
Quad type is forbidden by all the strict C++ standards, so using or adding -std=c++11 and later standards will prevent its use.
so explicitly use -std=gnu++11, 1y, 14, 17, or 1z or ...
For GCC 6.1.1, for example, the default is if no C++ language dialect options are given, is -std=gnu++14.
See https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html#C-Dialect-Options
https://gcc.gnu.org/onlinedocs/gcc/Standards.html#Standards 2 Language Standards Supported by GCC
g++.exe -Wall -fexceptions -std=gnu++17 -g -fext-numeric-literals -fpermissive -lquadmath
-II:\modular-boost\libs\math\include -Ii:\modular-boost -c J:\Cpp\float128\float128\float128_example.cpp -o obj\Debug\float128_example.o
Requires GCC linker option -lquadmath
If this is missing, then get errors like:
\modular-boost\boost\multiprecision\float128.hpp|210|undefined reference to `quadmath_snprintf'|
\modular-boost\boost\multiprecision\float128.hpp|351|undefined reference to `sqrtq'|
Requires compile option
-fext-numeric-literals
If missing, then get errors like:
\modular-boost\libs\math\include/boost/math/cstdfloat/cstdfloat_types.hpp:229:43: error: unable to find numeric literal operator 'operator""Q'
A successful build log was:
g++.exe -Wall -std=c++11 -fexceptions -std=gnu++17 -g -fext-numeric-literals -II:\modular-boost\libs\math\include -Ii:\modular-boost -c J:\Cpp\float128\float128\float128_example.cpp -o obj\Debug\float128_example.o
g++.exe -o bin\Debug\float128.exe obj\Debug\float128_example.o -lquadmath
*/
//] [/float128_dialect_1]
void show_versions(std::string title)
{
std::cout << title << std::endl;
std::cout << "Platform: " << BOOST_PLATFORM << '\n'
<< "Compiler: " << BOOST_COMPILER << '\n'
<< "STL : " << BOOST_STDLIB << '\n'
<< "Boost : " << BOOST_VERSION / 100000 << "."
<< BOOST_VERSION / 100 % 1000 << "."
<< BOOST_VERSION % 100
<< std::endl;
#ifdef _MSC_VER
std::cout << "_MSC_FULL_VER = " << _MSC_FULL_VER << std::endl; // VS 2015 190023026
#if defined _M_IX86
std::cout << "(x86)" << std::endl;
#endif
#if defined _M_X64
std::cout << " (x64)" << std::endl;
#endif
#if defined _M_IA64
std::cout << " (Itanium)" << std::endl;
#endif
// Something very wrong if more than one is defined (so show them in all just in case)!
#endif // _MSC_VER
#ifdef __GNUC__
//PRINT_MACRO(__GNUC__);
//PRINT_MACRO(__GNUC_MINOR__);
//PRINT_MACRO(__GNUC_PATCH__);
std::cout << "GCC " << __VERSION__ << std::endl;
//PRINT_MACRO(LONG_MAX);
#endif // __GNUC__
return;
} // void show_version(std::string title)
int main()
{
try
{
//[float128_example_3
// Always use try'n'catch blocks to ensure any error messages are displayed.
//`Ensure that all possibly significant digits (17) including trailing zeros are shown.
std::cout.precision(std::numeric_limits<boost::float64_t>::max_digits10);
std::cout.setf(std::ios::showpoint); // Show all significant trailing zeros.
//] [/ float128_example_3]
#ifdef BOOST_FLOAT128_C
std::cout << "Floating-point type boost::float128_t is available." << std::endl;
std::cout << " std::numeric_limits<boost::float128_t>::digits10 == "
<< std::numeric_limits<boost::float128_t>::digits10 << std::endl;
std::cout << " std::numeric_limits<boost::float128_t>::max_digits10 == "
<< std::numeric_limits<boost::float128_t>::max_digits10 << std::endl;
#else
std::cout << "Floating-point type boost::float128_t is NOT available." << std::endl;
#endif
show_versions("");
using boost::multiprecision::float128; // Wraps, for example, __float128 or _Quad.
// or
//using namespace boost::multiprecision;
std::cout.precision(std::numeric_limits<float128>::max_digits10); // Show all potentially meaningful digits.
std::cout.setf(std::ios::showpoint); // Show all significant trailing zeros.
// float128 pi0 = boost::math::constants::pi(); // Compile fails - need to specify a type for the constant!
float128 pi1 = boost::math::constants::pi<float128>(); // Returns a constant of type float128.
std::cout << sqrt(pi1) << std::endl; // 1.77245385090551602729816748334114514
float128 pi2 = boost::math::constants::pi<__float128>(); // Constant of type __float128 gets converted to float128 on the assignment.
std::cout << sqrt(pi2) << std::endl; // 1.77245385090551602729816748334114514
// DIY decimal digit literal constant, with suffix Q.
float128 pi3 = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348Q;
std::cout << sqrt(pi3) << std::endl; // 1.77245385090551602729816748334114514
// Compare to ready-rolled sqrt(pi) constant from Boost.Math:
std::cout << boost::math::constants::root_pi<float128>() << std::endl; // 1.77245385090551602729816748334114514
// DIY decimal digit literal constant, without suffix Q, suffering seventeen silent digits loss of precision!
float128 pi4 = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348;
std::cout << sqrt(pi4) << std::endl; // 1.77245385090551599275151910313924857
// float128 variables constructed from a quad-type literal can be declared constexpr if required:
#ifndef BOOST_NO_CXX11_CONSTEXPR
constexpr float128 pi_constexpr = 3.1415926535897932384626433832795028841971693993751058Q;
#endif
std::cout << pi_constexpr << std::endl; // 3.14159265358979323846264338327950280
// But sadly functions like sqrt are not yet available constexpr for float128.
// constexpr float128 root_pi_constexpr = sqrt(pi_constexpr); // Fails - not constexpr (yet).
// constexpr float128 root_pi_constexpr = std::sqrt(pi_constexpr); // Fails - no known conversion for argument 1 from 'const float128'.
// constexpr float128 root_pi_constexpr = sqrt(pi_constexpr); // Call to non-constexpr
// constexpr float128 root_pi_constexpr = boost::math::constants::root_pi(); // Missing type for constant.
// Best current way to get a constexpr is to use a Boost.Math constant if one is available.
constexpr float128 root_pi_constexpr = boost::math::constants::root_pi<float128>();
std::cout << root_pi_constexpr << std::endl; // 1.77245385090551602729816748334114514
// Note that casts within the sqrt call are NOT NEEDED (nor allowed),
// since all the variables are the correct type to begin with.
// std::cout << sqrt<float128>(pi3) << std::endl;
// But note examples of catastrophic (but hard to see) loss of precision below.
// Note also that the library functions, here sqrt, is NOT defined using std::sqrt,
// so that the correct overload is found using Argument Dependent LookUp (ADL).
float128 ee = boost::math::constants::e<float128>();
std::cout << ee << std::endl; // 2.71828182845904523536028747135266231
float128 e1 = exp(1.Q); // Note argument to exp is type float128.
std::cout << e1 << std::endl; // 2.71828182845904523536028747135266231
// Beware - it is all too easy to silently get a much lower precision by mistake.
float128 e1d = exp(1.); // Caution - only double 17 decimal digits precision!
std::cout << e1d << std::endl; // 2.71828182845904509079559829842764884
float128 e1i = exp(1); // Caution int promoted to double so only 17 decimal digits precision!
std::cout << e1i << std::endl; // 2.71828182845904509079559829842764884
float f1 = 1.F;
float128 e1f = exp(f1); // Caution float so only 6 decimal digits precision out of 36!
std::cout << e1f << std::endl; // 2.71828174591064453125000000000000000
// In all these cases you get what you asked for and not what you expected or wanted.
// Casting is essential if you start with a lower precision type.
float128 e1q = exp(static_cast<float128>(f1)); // Full 36 decimal digits precision!
std::cout << e1q << std::endl; // 2.71828182845904523536028747135266231
float128 e1qc = exp((float128)f1); // Full 36 decimal digits precision!
std::cout << e1qc << std::endl; // 2.71828182845904523536028747135266231
float128 e1qcc = exp(float128(f1)); // Full 36 decimal digits precision!
std::cout << e1qcc << std::endl; // 2.71828182845904523536028747135266231
//float128 e1q = exp<float128>(1.); // Compile fails.
// std::cout << e1q << std::endl; //
// http://en.cppreference.com/w/cpp/language/typeid
// The name()is implementation-dependent mangled, and may not be able to be output.
// The example showing output using one of the implementations where type_info::name prints full type names;
// filter through c++filt -t if using gcc or similar.
//[float128_type_info
const std::type_info& tifu128 = typeid(__float128); // OK.
std::cout << " tifu128.name() = " << tifu128.name() << std::endl;
std::cout << " typeid(__float128).name() = " << typeid(__float128).name() << std::endl;
const std::type_info& tif128 = typeid(float128); // OK.
std::cout << tif128.name() << std::endl; // OK.
std::cout << typeid(float128).name() << std::endl; // OK.
const std::type_info& tpi = typeid(pi1); // OK using GCC 6.1.1.
// (from GCC 5 according to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43622)
std::cout << tpi.name() << std::endl; // OK, Output implementation-dependent mangled name:
// N5boost14multiprecision6numberINS0_8backends16float128_backendELNS0_26expression_template_optionE0EEE
//] [/float128_type_info]
}
catch (std::exception ex)
{ // Display details about why any exceptions are thrown.
std::cout << "Thrown exception " << ex.what() << std::endl;
}
} // int main()
'프로그래밍 > C++' 카테고리의 다른 글
C++ 언어에서 큰 부동소수점수(native double) 의 정확도 (0) | 2023.03.19 |
---|---|
부동소수점수의 소수점 아래에 홑 따옴표 문자 ' 붙여서 가독성 높이기 (0) | 2023.01.03 |
맥 OS X에 gmplib 6.2.1 설치하고 g++로 설치 테스트하기 (0) | 2022.03.19 |
Boost Library를 이용하여 임의의 정밀도를 갖는 부동소수점수 계산하기 (0) | 2021.03.29 |
new 키워드로 생성된 배열의 크기 변경하여 재할당하기 (0) | 2021.02.24 |