Skip to content

Instantly share code, notes, and snippets.

@chuntaro
Created December 11, 2019 05:40
Show Gist options
  • Select an option

  • Save chuntaro/e902cee53dd48934ae4051d37e00de4a to your computer and use it in GitHub Desktop.

Select an option

Save chuntaro/e902cee53dd48934ae4051d37e00de4a to your computer and use it in GitHub Desktop.
リーダブル(入力⇔出力で値が変わらない)な浮動小数文字列を出力するC言語の関数(snprintf_double)
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int snprint_double(char* buf, int size, double f)
{
if (isnan(f)) {
return snprintf(buf, size, "%s", signbit(f) ? "-nan" : "+nan");
} else if (isinf(f)) {
return snprintf(buf, size, "%s", signbit(f) ? "-inf" : "+inf");
} else {
int len;
for (int prec = fabs(f) < DBL_MIN ? 1 : DBL_DIG; ; ++prec) {
len = snprintf(buf, size, "%.*g", prec, f);
if (len < 0) {
return 0;
}
if (16 < prec
|| (len < size && strtod(buf, NULL) == f)) {
break;
}
}
// 12.0 が 12 と表示されるのを回避する場合は以下を有効にする
#if 0
int need_decimal_point = 1;
for (const char* p = buf; *p; ++p) {
if (*p == '.' || *p == 'e') {
need_decimal_point = 0;
break;
}
}
if (need_decimal_point && len <= (int)sizeof(buf) - 2) {
buf[len++] = '.';
buf[len++] = '0';
}
#endif
return len;
}
}
#if 1
int main(void)
{
static const char* numbers[] = {
"-78888.032505798281119254395134273686797671268736553338536795406087720787378465858094159870726039767164607546644",
"-68.272904537112324",
"-9034540.e14",
"8113.",
"8.4e-5",
"-22201639700171564.74311",
"-8954192320392299.8381203",
"-17917743150860613.3220670",
"-639.e19",
"-.7110489997872715289749e17",
"0660.",
"29550600.1079e9",
"61748105994541732.55867883500",
"-68343557483.e7",
"978021552.497e19",
"-.8e17",
"36932659236092295.0",
"-91401616.e27",
"36480499517288025.0542900284",
"428069624325376740.86",
"-21555778236601032.2",
"-19955484380340809.67942279917",
"064192082488816174.20389",
"20883828695083711.450",
"-29.e21",
"25974673343120767.984",
"56154525620347983.0704789",
"54232355670202146.92",
"-40.4e21",
"23476370748988750.",
"25320799998182632.0715",
"-0440991669613565547.9",
"-24009465153285070.374",
"-20711179850745286.003484",
"68677973679788178.433",
"-24969950846291642195900.92e-5",
"-21754109068434992.183",
"34050527959032390.7765690846",
"37488855950257261.93224",
"-.80e24",
"-78330960058723814.52",
"-822.02024e18",
"-29888056775088510.8060768",
"-020530861637945047.436065",
"-571586105612962456.",
"42175547254159376.57849591399",
"21.1642403153e17",
"90518747605325402.26566",
"63845556111770813.1",
"-841492335808263887.72",
"19593618780424409.60",
"-133218.918423061e12",
"-69588228482826904.23379252806",
"-46437062846140.107706478e3",
"60082583768504096.5903",
"-83231118366109006.5642058255",
"31598016798861313.0529581586",
"-461003734889001005558274390.1e-10",
"-59882208171768905.872394",
"27075008032386633.6570401",
"045158893397659345.08972",
"-4.157065105787774e-309",
"-3e-309",
};
for (int i = 0; i < (int)(sizeof(numbers)/sizeof(numbers[0])); ++i) {
const char* number = numbers[i];
char* endptr;
double d0 = strtod(number, &endptr);
char buf[2048];
int len = snprint_double(buf, sizeof(buf), d0);
double d1 = strtod(buf, &endptr);
if (d0 != d1) {
printf("Oops! %s\n", number);
return 1;
} else {
printf("OK %s -> %.*s\n", number, len, buf);
}
}
printf("Complete!\n");
return 0;
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment