char * Parser::DoubleToString(double value) { int decimal, sign; char* res = (char*)heap_my.get_mem(_CVTBUFSIZE); int buf = _ecvt_s(res, _CVTBUFSIZE, value, 100, &decimal, &sign); if (buf != 0) return nullptr; return res; }
int _tmain(int argc, _TCHAR* argv[]) { size_t max_num = 100000000; const int max_char_per_float = 10; const size_t buffer_element_count = 100000; size_t buffer_byte_size = buffer_element_count * (max_char_per_float + 5); char* write_buffer = new char[buffer_byte_size]; HANDLE hFile = ::CreateFile(L"output.txt", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, NULL); // std::ofstream output(); for (size_t i=0; i < max_num / buffer_element_count; ++i) { int buffer_position = 0; for (int k = 0; k < buffer_element_count; ++k) { char number_buffer[32]; int pos = 0; int dec; int sign; float random = float(rand()) / RAND_MAX; _ecvt_s(number_buffer, random, max_char_per_float, &dec, &sign); if (sign) { write_buffer[buffer_position++] = '-'; } while(pos<dec) { write_buffer[buffer_position++] = number_buffer[pos++]; } write_buffer[buffer_position++] = '.'; while (number_buffer[pos]) { write_buffer[buffer_position++] = number_buffer[pos++]; } write_buffer[buffer_position++] = '\r'; write_buffer[buffer_position++] = '\n'; } DWORD bytes_written = 0; ::WriteFile(hFile, write_buffer, buffer_position, &bytes_written, NULL); } ::CloseHandle(hFile); return 0; }
void print(double val, buffered_ostream<CharT>& os) { char buf[_CVTBUFSIZE]; int decimal_point = 0; int sign = 0; if (precision_ >= _CVTBUFSIZE) { precision_ = _CVTBUFSIZE - 1; } int err = _ecvt_s(buf, _CVTBUFSIZE, val, precision_, &decimal_point, &sign); if (err != 0) { throw std::runtime_error("Failed attempting double to string conversion"); } char* s = buf; char* se = s + precision_; int i, k; int j; if (sign) { os.put('-'); } if (decimal_point <= -4 || decimal_point > se - s + 5) { os.put(*s++); if (s < se) { os.put('.'); while ((se-1) > s && *(se-1) == '0') { --se; } while(s < se) { os.put(*s++); } } os.put('e'); /* sprintf(b, "%+.2d", decimal_point - 1); */ if (--decimal_point < 0) { os.put('-'); decimal_point = -decimal_point; } else os.put('+'); for(j = 2, k = 10; 10*k <= decimal_point; j++, k *= 10); for(;;) { i = decimal_point / k; os.put(i + '0'); if (--j <= 0) break; decimal_point -= i*k; decimal_point *= 10; } } else if (decimal_point <= 0) { os.put('0'); os.put('.'); while ((se-1) > s && *(se-1) == '0') { --se; } for(; decimal_point < 0; decimal_point++) { os.put('0'); } while(s < se) { os.put(*s++); } } else { while(s < se) { os.put(*s++); if ((--decimal_point == 0) && s < se) { os.put('.'); while ((se-1) > s && *(se-1) == '0') { --se; } } } for(; decimal_point > 0; decimal_point--) { os.put('0'); } } }
int _tmain(int argc, _TCHAR* argv[]) { const size_t max_num = 100000000; const int buffer_element_count = 10000; const int max_float_digits = 10; // Init critical section; InitializeCriticalSection(&g_write_queue_cs); HANDLE hFile = ::CreateFile(L"output.txt", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { printf("Oppps"); exit(-1); } // Launch a writer thread. HANDLE hThread = CreateThread(NULL, 0, &WriteThreadProc, hFile,0, 0); // std::ofstream output(); for (size_t i=0; i < max_num / buffer_element_count; ++i) { // Prepare a block of numbers for writing. WriteBuffer* write_buffer = new WriteBuffer(buffer_element_count, max_float_digits); char* write_ptr = write_buffer->ptr_; for (int k = 0; k < buffer_element_count; ++k) { // Format each float to string and append to buffer. char number_micro_buffer[32]; int pos = 0; int dec; int sign; float random = float(rand()) / RAND_MAX; _ecvt_s(number_micro_buffer, random, max_float_digits, &dec, &sign); if (sign) { *(write_ptr++) = '-'; } if (dec <=0) { *(write_ptr++) = '0'; } while(pos<dec) { *(write_ptr++) = number_micro_buffer[pos++]; } *(write_ptr++) = '.'; while (number_micro_buffer[pos]) { *(write_ptr++) = number_micro_buffer[pos++]; } *(write_ptr++) = '\r'; *(write_ptr++) = '\n'; } // Compute how many bytes to write. write_buffer->useful_data_size_ = write_ptr - write_buffer->ptr_; // Enqueue for writing. EnterCriticalSection(&g_write_queue_cs); g_write_queue.push(write_buffer); LeaveCriticalSection(&g_write_queue_cs); } g_done = true; WaitForSingleObject(hThread, INFINITE); ::CloseHandle(hFile); return 0; }
char * dtoa(double d, // IN int mode, // IN int prec, // IN int *expOut, // OUT int *sign, // OUT char **strEnd) // OUT { char *str = NULL; int dec; #if defined(_WIN32) if (2 == mode) { str = malloc(_CVTBUFSIZE); if (str) { if (_ecvt_s(str, _CVTBUFSIZE, d, prec, &dec, sign)) { free(str); str = NULL; } } } else { ASSERT(3 == mode); str = malloc(_CVTBUFSIZE); if (str) { if (_fcvt_s(str, _CVTBUFSIZE, d, prec, &dec, sign)) { free(str); str = NULL; } } /* * When the value is not zero but rounds to zero at prec digits, * the Windows fcvt() sometimes returns the empty string and * a negative dec that goes too far (as in -dec > prec). * For example, converting 0.001 with prec 1 results in * the empty string and dec -2. (See bug 253674.) * * We just clamp dec to -prec when this happens. * * While this may appear to be a safe and good thing to * do in general. It really only works when the result is * all zeros or empty. Since checking for all zeros is * expensive, we only check for empty string, which works * for this bug. */ if (str && *str == '\0' && dec < 0 && dec < -prec) { dec = -prec; } } #else // _WIN32 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; if (2 == mode) { pthread_mutex_lock(&mutex); str = strdup(ecvt(d, prec, &dec, sign)); pthread_mutex_unlock(&mutex); } else { ASSERT(3 == mode); #ifdef __APPLE__ /* * The Mac fcvt() returns "" when prec is 0, so we have to * compensate. See bug 233530. * While it is conceivable that fcvt(round(d), 1) can return * a string that doesn't end in 0, it doesn't seem to happen * in practice (on the Mac). The problematic case that we * want to avoid is a last digit greater than 4, which requires * rounding up, which we don't want to do, which is why we're * doing the rounding on the number instead of after fcvt() * in the first place. * -- edward */ if (prec == 0) { size_t l; pthread_mutex_lock(&mutex); str = strdup(fcvt(round(d), 1, &dec, sign)); pthread_mutex_unlock(&mutex); if (str) { l = strlen(str); ASSERT(l > 0); l--; ASSERT(str[l] == '0'); str[l] = '\0'; } } else #endif // __APPLE__ { pthread_mutex_lock(&mutex); str = strdup(fcvt(d, prec, &dec, sign)); pthread_mutex_unlock(&mutex); } } #endif // _WIN32 if (str) { *strEnd = str + strlen(str); /* strip trailing zeroes */ while ((*strEnd > str) && ('0' == *((*strEnd) - 1))) { (*strEnd)--; } *expOut = dec; } return str; }
std::basic_string<Char> float_to_string(double val, size_t precision) { std::basic_string<Char> s; char buf[_CVTBUFSIZE]; int decimal_point = 0; int sign = 0; if (precision >= _CVTBUFSIZE) { precision = _CVTBUFSIZE - 1; } int err = _ecvt_s(buf, _CVTBUFSIZE, val, static_cast<int>(precision), &decimal_point, &sign); if (err != 0) { throw std::runtime_error("Failed attempting double to string conversion"); } if (sign != 0) { s.push_back('-'); } int len = static_cast<int>(precision); int decimal; int exponent; if (decimal_point < 0 || decimal_point > len) { decimal = 1; exponent = decimal_point - 1; } else { decimal = decimal_point; exponent = 0; } while (len >= 2 && buf[len - 1] == '0' && (len - 1) != decimal) { --len; } if (decimal == 0) { s.push_back('0'); s.push_back('.'); } s.push_back(buf[0]); for (int i = 1; i < len; ++i) { if (i == decimal) { s.push_back('.'); } s.push_back(buf[i]); } if (exponent != 0) { s.push_back('e'); if (exponent > 0) { s.push_back('+'); } int err2 = _itoa_s(exponent,buf,_CVTBUFSIZE,10); if (err2 != 0) { throw std::runtime_error("Failed attempting double to string conversion"); } for (int i = 0; i < _CVTBUFSIZE && buf[i]; ++i) { s.push_back(buf[i]); } } return s; }