নির্ভুলতা এবং নির্দিষ্ট দশমিক অঙ্কের সংখ্যার সাথে স্ট্রিংয়ে ফ্লোটকে রূপান্তর করবেন?


91

দশমিক অঙ্কের নির্ভুলতা এবং সংখ্যা নির্দিষ্ট করার সময় আপনি কীভাবে ফ্লোটকে সি ++ তে স্ট্রিংয়ে রূপান্তর করবেন?

উদাহরণ স্বরূপ: 3.14159265359 -> "3.14"


আপনি যে নির্দিষ্ট নির্ভুলতা চান তা দিয়ে কেন একটি টেম্প ফ্লোট তৈরি করে তারপরে স্ট্রিংয়ে রূপান্তর করবেন না?
গিলাদ

@ গিলাদ 'টেম্প ফ্লোট'-এর' নির্দিষ্ট নির্দিষ্টতা 'নেই এবং এমন ঘটনাও ঘটে যখন এই জাতীয় দৃষ্টিভঙ্গি ভেঙে যায়। এই প্রশ্নটি মূলত ""% .2f "ফর্ম্যাটের সমতুল্য কি" জিজ্ঞাসার মতো?
ব্যবহারকারীর 2864740

4
যদি আইও-র প্রয়োজন হয় তবে এটি স্ট্যাকওভারফ্লো / প্রশ্নগুলি / 14432043/c-float- formattting দেখুন ।
ব্যবহারকারী 2864740

উত্তর:


133

একটি সাধারণ উপায় হ'ল ব্যবহার করা stringstream:

#include <iomanip>
#include <sstream>

double pi = 3.14159265359;
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << pi;
std::string s = stream.str();

স্থির দেখুন

স্থির ভাসমান-পয়েন্ট স্বরলিপি ব্যবহার করুন

সেট floatfieldজন্য বিন্যাস পতাকা Str স্ট্রীমের fixed

যখন floatfieldসেট করা থাকে fixed, ফ্লোটিং-পয়েন্ট মানগুলি স্থির-পয়েন্ট স্বরলিপি ব্যবহার করে রচনা করা হয়: যথার্থ ক্ষেত্র ( precision) দ্বারা নির্দিষ্ট হিসাবে দশমিক অংশে হুবহু হ'ল সংখ্যার সাথে মানটি উপস্থাপন করা হয় এবং কোনও খাঁটি অংশ না দিয়ে।

এবং সংজ্ঞা


জন্য প্রযুক্তিগত উদ্দেশ্যের ধর্মান্তর , XML বা JSON ফাইল, সি ++ 17 মাত্রা নির্ধারণ করে ডেটা সঞ্চয় করার মত to_chars ফাংশন পরিবার।

একটি কমপ্লায়েন্ট সংকলক (যা লেখার সময় আমাদের অভাব হয়) ধরে নেওয়া, এরকম কিছু বিবেচনা করা যেতে পারে:

#include <array>
#include <charconv>

double pi = 3.14159265359;
std::array<char, 128> buffer;
auto [ptr, ec] = std::to_chars(buffer.data(), buffer.data() + buffer.size(), pi,
                               std::chars_format::fixed, 2);
if (ec == std::errc{}) {
    std::string s(buffer.data(), ptr);
    // ....
}
else {
    // error handling
}

31

এই ধরণের জিনিস করার প্রথাগত পদ্ধতি হ'ল "মুদ্রণ থেকে স্ট্রিং"। সি ++ এ এর ​​অর্থ std::stringstreamএমন কিছু ব্যবহার করা :

std::stringstream ss;
ss << std::fixed << std::setprecision(2) << number;
std::string mystring = ss.str();

13

আরেকটি বিকল্প হ'ল snprintf:

double pi = 3.1415926;

std::string s(16, '\0');
auto written = std::snprintf(&s[0], s.size(), "%.2f", pi);
s.resize(written);

ডেমো । ত্রুটি পরিচালনায় যুক্ত করা উচিত, অর্থাত্ পরীক্ষা করাwritten < 0


snprintfএই ক্ষেত্রে কেন ভাল হবে ? দয়া করে ব্যাখ্যা করুন ... এটি অবশ্যই দ্রুত হবে না, কম কোড তৈরি করুন [আমি একটি প্রিন্টফ বাস্তবায়ন লিখেছি, এটি কেবল 2000 লাইনের কোডের নীচে মোটামুটি কমপ্যাক্ট, তবে ম্যাক্রো বিস্তৃতিতে প্রায় 2500 লাইনে
পৌঁছেছে

4
@ ম্যাটস পিটারসন আমি দৃ strongly়ভাবে বিশ্বাস করি যে এটি আরও দ্রুত হবে। এই কারণেই আমি এই উত্তরটি প্রথম স্থানে রেখেছি।
কলম্বো

@ ম্যাটস পিটারসন আমি পরিমাপ সম্পাদন করেছি (জিসিসি 4.8.1, -ओ 2) যা সূচিত করে যে স্নিপ্রিন্টফ প্রকৃতপক্ষে 17/22 ফ্যাক্টর দ্বারা কম সময় নিচ্ছে। আমি শীঘ্রই কোডটি আপলোড করব।
কলম্বো

@ ম্যাটস পিটারসন আমার বেঞ্চমার্কটি সম্ভবত ত্রুটিযুক্ত, তবে স্ট্রিংস্ট্রিম সংস্করণটি স্নিপ্রিন্টফ সংস্করণ হিসাবে 1000000 পুনরাবৃত্তিতে দ্বিগুণ দীর্ঘ সময় নিতে হবে (কলম্বিত ৩.7.০, লিবস্টডিসি ++, -ओ 2)।

আমি কিছু পরিমাপও করেছি - এবং এটি (কমপক্ষে লিনাক্সে) মনে হবে যে স্ট্রিংস্ট্রিম এবং স্নিপ্রিন্টফ উভয় একই অন্তর্নিহিত __printf_fpকার্যকারিতা ব্যবহার করে - এটি বরং আশ্চর্যের বিষয় যে এটি এতটা বেশি সময় নেয় stringstream, কারণ এটি সত্যই হওয়া উচিত ছিল না।
ম্যাটস পিটারসন

10

আপনি সি ++ 20 ব্যবহার করতে পারেন std::formatবা fmt::formatথেকে ফাংশন {FMT} গ্রন্থাগার , std::formatউপর ভিত্তি করে:

#include <fmt/core.h>

int main()
  std::string s = fmt::format("{:.2f}", 3.14159265359); // s == "3.14"
}

2একটি নির্ভুলতা যেখানে ।


8

এখানে শুধুমাত্র একটি স্ট্যান্ডার্ড ব্যবহার করে একটি সমাধান। যাইহোক, নোট করুন যে এটি কেবল গোলাকার হবে।

    float number = 3.14159;
    std::string num_text = std::to_string(number);
    std::string rounded = num_text.substr(0, num_text.find(".")+3);

জন্য roundedএটা উৎপাদ:

3.14

কোডটি পুরো ফ্লোটটিকে স্ট্রিংয়ে রূপান্তরিত করে, তবে "" এর পরে সমস্ত অক্ষর 2 অক্ষর কেটে দেয়। "


কেবল জিনিসটি এই যে আপনি আসলে সংখ্যাটি গোল করে নিচ্ছেন না।
ChrCury78

4
আমার ক্রিয়াকুরি @78 হিসাবে আমার উত্তরে বলা হয়েছে এটি কেবলমাত্র চলাফেরা করে। আপনি যদি কোনও সাধারণ রাউন্ডিং চান তবে আপনার মান অনুসরণ করে ডাইজেটে 5 টি যুক্ত করুন। যেমন number + 0.005আমার ক্ষেত্রে।
সেবাস্তিয়ান আর।

3

এখানে আমি একটি নেতিবাচক উদাহরণ সরবরাহ করছি যেখানে ভাসমান সংখ্যাটি স্ট্রিংয়ে রূপান্তর করার সময় আপনি এড়াতে চান।

float num=99.463;
float tmp1=round(num*1000);
float tmp2=tmp1/1000;
cout << tmp1 << " " << tmp2 << " " << to_string(tmp2) << endl;

তুমি পাও

99463 99.463 99.462997

দ্রষ্টব্য: নম্বর ভেরিয়েবলের মান 99.463 এর কাছাকাছি কোনও মান হতে পারে, আপনি একই প্রিন্ট আউট পাবেন। মূল বিষয়টি হ'ল সুবিধাজনক সি ++ 11 "টু স্ট্রিং" ফাংশন এড়ানো। এই ফাঁদটি পেতে আমাকে কিছুটা সময় লেগেছে। সর্বোত্তম উপায় হ'ল স্ট্রিংস্ট্রিম এবং স্প্রিন্টফ পদ্ধতিগুলি (সি ভাষা)। সি ++ 11 বা আরও নতুন দেখানোর জন্য ভাসমান পয়েন্টের পরে অঙ্কের সংখ্যা হিসাবে একটি দ্বিতীয় প্যারামিটার সরবরাহ করা উচিত। এখনই ডিফল্ট 6 I আমি এটি পোস্ট করছি যাতে অন্যরা এই বিষয়ে সময় নষ্ট না করে।

আমি আমার প্রথম সংস্করণটি লিখেছি, দয়া করে আপনার যদি ঠিক করা দরকার এমন কোনও বাগ খুঁজে পান তবে আমাকে জানান। আপনি iomanipulator এর সাথে সঠিক আচরণটি নিয়ন্ত্রণ করতে পারেন। আমার কাজটি দশমিক বিন্দুর পরে অঙ্কের সংখ্যা দেখানোর জন্য।

string ftos(float f, int nd) {
   ostringstream ostr;
   int tens = stoi("1" + string(nd, '0'));
   ostr << round(f*tens)/tens;
   return ostr.str();
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.