দশমিক স্থানে ডাবল স্থানে চলেছে


98

সুতরাং আমার দ্বিগুণ সেট হয়েছে 1234 এর সমান, আমি দশমিক স্থানটিকে 12.34 করে তুলতে চাই

সুতরাং এটি করার জন্য আমি .1 থেকে 1234 বার দুবার গুণ করব, এ জাতীয় পছন্দ করুন

double x = 1234;
for(int i=1;i<=2;i++)
{
  x = x*.1;
}
System.out.println(x);

এটি "12.34000000000000002" ফলাফল মুদ্রণ করবে

ডাবল স্টোরটি সঠিকভাবে 12.34 করার জন্য দুটি দশমিক স্থানে বিন্যাস না করে কি কোনও উপায় আছে?



43
আপনি না করার কোন কারণ আছে x /= 100;?
মার্ক ইঙ্গ্রাম

উত্তর:


190

আপনি যদি ব্যবহার করেন doubleবা float, আপনার গোলাকার ব্যবহার করা উচিত বা কিছু গোলাকার ত্রুটি দেখার আশা করা উচিত। আপনি যদি এটি করতে না পারেন তবে ব্যবহার করুনBigDecimal

আপনার সমস্যাটি হ'ল 0.1 হুবহু উপস্থাপনা নয় এবং দুবার গণনা সম্পাদন করে আপনি সেই ত্রুটিটিকে আরও জটিল করে তুলছেন।

তবে, 100 সঠিকভাবে উপস্থাপন করা যায়, তাই চেষ্টা করুন:

double x = 1234;
x /= 100;
System.out.println(x);

যা প্রিন্ট করে:

12.34

এটি কাজ করে কারণ Double.toString(d)আপনার পক্ষ থেকে অল্প পরিমাণে রাউন্ডিং করে তবে এটি খুব বেশি নয় much আপনি যদি ভাবছেন যে গোল না করে এটি দেখতে কেমন দেখাচ্ছে:

System.out.println(new BigDecimal(0.1));
System.out.println(new BigDecimal(x));

মুদ্রণ:

0.100000000000000005551115123125782702118158340454101562
12.339999999999999857891452847979962825775146484375

সংক্ষেপে, ভাসমান পয়েন্টে বুদ্ধিমান জবাবগুলির জন্য বৃত্তাকারটি অপরিহার্য is


দ্রষ্টব্য: রাউন্ডিং ত্রুটির ক্ষেত্রে x / 100এবং x * 0.01ঠিক একই রকম হয় না। কারণ প্রথম প্রকাশের জন্য রাউন্ড ত্রুটিটি x এর মানগুলির উপর নির্ভর করে, যখন 0.01দ্বিতীয়টিতে একটি নির্দিষ্ট রাউন্ড ত্রুটি থাকে।

for(int i=0;i<200;i++) {
    double d1 = (double) i / 100;
    double d2 = i * 0.01;
    if (d1 != d2)
        System.out.println(d1 + " != "+d2);
}

প্রিন্ট

0.35 != 0.35000000000000003
0.41 != 0.41000000000000003
0.47 != 0.47000000000000003
0.57 != 0.5700000000000001
0.69 != 0.6900000000000001
0.7 != 0.7000000000000001
0.82 != 0.8200000000000001
0.83 != 0.8300000000000001
0.94 != 0.9400000000000001
0.95 != 0.9500000000000001
1.13 != 1.1300000000000001
1.14 != 1.1400000000000001
1.15 != 1.1500000000000001
1.38 != 1.3800000000000001
1.39 != 1.3900000000000001
1.4 != 1.4000000000000001
1.63 != 1.6300000000000001
1.64 != 1.6400000000000001
1.65 != 1.6500000000000001
1.66 != 1.6600000000000001
1.88 != 1.8800000000000001
1.89 != 1.8900000000000001
1.9 != 1.9000000000000001
1.91 != 1.9100000000000001

26
আমি বিশ্বাস করতে পারি না যে আমি প্রথমে এটি করার কথা ভাবিনি! ধন্যবাদ :
পি

6
যদিও 100 বাইনারি ফর্ম্যাটে হুবহু উপস্থাপন করা যায় তবে 100 দ্বারা বিভাজনকে সঠিকভাবে উপস্থাপন করা যায় না। সুতরাং, 1234/100যেমন লেখার কাজটি করেছেন তেমনি অন্তর্নিহিত সমস্যাটি সম্পর্কে সত্যই কিছুই করেন না - এটি লেখার ঠিক সমান হওয়া উচিত 1234 * 0.01
ব্রুকস মুসা

4
@ পিটার ল্যারি: আপনি কী আরও সংখ্যক বিজোড় বা এমনকি রাউন্ডিংকে প্রভাব ফেলবেন তা কেন ব্যাখ্যা করতে পারেন? আমি ভেবেছিলাম যে / = 100 এবং * =। 01 একই হবে কারণ যদিও 100 ইনট হলেও এটি টাইপ জবরদস্তির ফলে এটি যাইহোক 100.0 তে রূপান্তরিত হবে।

4
/100এবং *0.01একে অপরের সমতুল্য, তবে ওপি'র নয় *0.1*0.1
আমদান

4
আমি যা বলছি তা হ'ল 0.1 বার দ্বিগুণ করা একবারে 0.01 দ্বারা একবারে গুণনের চেয়ে আরও বড় ত্রুটি প্রবর্তন করবে; তবে আমি আনন্দের সাথে @ জ্যাসপারবেকার্সের বক্তব্যটি প্রায় দ্বি-দ্বি-উপস্থাপিত হয়ে প্রায় 100 আলাদা হওয়ার বিষয়টি স্বীকার করব।
আমাদান

52

না - আপনি যদি দশমিক মানগুলি নির্ভুলভাবে সঞ্চয় করতে চান তবে ব্যবহার করুন BigDecimaldoubleকেবলমাত্র ০.১ এর মতো একটি সংখ্যা উপস্থাপন করতে পারে না , আপনি দশমিক অঙ্কের একটি সীমাবদ্ধ অঙ্কের সাথে তৃতীয়টির মান ঠিক লিখতে পারেন তার চেয়ে বেশি।


46

যদি এটি কেবল ফর্ম্যাট করে তবে প্রিন্টফ ব্যবহার করে দেখুন

double x = 1234;
for(int i=1;i<=2;i++)
{
  x = x*.1;
}
System.out.printf("%.2f",x);

আউটপুট

12.34

8
উচ্চতর রেটযুক্ত উত্তরগুলি আরও প্রযুক্তিগতভাবে অন্তর্দৃষ্টিযুক্ত, তবে এটি ওপির সমস্যার সঠিক উত্তর। আমরা সাধারণত দ্বিগুণের সামান্য অসম্পূর্ণতা সম্পর্কে চিন্তা করি না , তাই বিগডিসিমাল ওভারকিল হয় তবে প্রদর্শিত হওয়ার সময় আমরা প্রায়শই আমাদের আউটপুটটি আমাদের স্বজ্ঞাততার সাথে মেলে তা নিশ্চিত করতে চাই, তাই সঠিক পথটিও System.out.printf()
dimo414

29

আর্থিক সফ্টওয়্যারে পেনিগুলির জন্য পূর্ণসংখ্যা ব্যবহার করা সাধারণ। স্কুলে, আমাদের শেখানো হয়েছিল কীভাবে ভাসমানের পরিবর্তে স্থির-পয়েন্টটি ব্যবহার করতে হয়, তবে এটি সাধারণত দুটিয়ের শক্তি। পূর্ণসংখ্যায় পেনিগুলি সংরক্ষণ করার সাথে সাথে "ফিক্সড পয়েন্ট" বলা যেতে পারে।

int i=1234;
printf("%d.%02d\r\n",i/100,i%100);

ক্লাসে, আমাদের সাধারণভাবে জিজ্ঞাসা করা হয়েছিল যে কোন সংখ্যাগুলিকে কোন বেসে ঠিক উপস্থাপন করা যায়।

এর জন্য base=p1^n1*p2^n2... আপনি যে কোনও এনকে প্রতিনিধিত্ব করতে পারেন যেখানে এন = এন * পি 1 ^ এম 1 * পি 2 ^ এম 2।

যাক base=14=2^1*7^1... আপনি 1/7 1/14 1/28 1/49 উপস্থাপন করতে পারেন তবে 1/3 নয়

আমি আর্থিক সফটওয়্যার সম্পর্কে জানি - আমি টিকিটমাস্টারের আর্থিক প্রতিবেদনকে ভ্যাক্স এএসএম থেকে পাস্কলে রূপান্তর করেছি। পেনিগুলির কোড সহ তাদের নিজস্ব ফরম্যাটলন () ছিল। রূপান্তরটির কারণ ছিল 32 বিট পূর্ণসংখ্যা আর যথেষ্ট ছিল না। +/- 2 বিলিয়ন পেনিগুলি 20 মিলিয়ন ডলার এবং এটি বিশ্বকাপ বা অলিম্পিকের জন্য উপচে পড়েছিল, আমি ভুলে গিয়েছিলাম।

আমি গোপনে শপথ করেছিলাম। আচ্ছা ভালো. একাডেমিতে, এটি প্রকাশিত হলে ভাল হয়; শিল্পে, আপনি এটি গোপন রাখবেন।


12

আপনি পূর্ণসংখ্যার সংখ্যা উপস্থাপন চেষ্টা করতে পারেন

int i =1234;
int q = i /100;
int r = i % 100;

System.out.printf("%d.%02d",q, r);

5
@ ডান: কেন? এটি এখনও হার্ডওয়্যার-স্তরের গতি বজায় রেখে আর্থিক অ্যাপ্লিকেশনগুলির (বা অন্য কোনও অ্যাপ্লিকেশান যেখানে একটি ক্ষুদ্রতর ত্রুটি এমনকি গ্রহণযোগ্য নয়) এর সঠিক পদ্ধতি। (অবশ্যই, এটি একটি শ্রেণিতে আবৃত হবে, সাধারণত, প্রতিবার লেখা হয় না)
আমদান

7
এই সমাধানটিতে সামান্য সমস্যা রয়েছে - যদি rবাকীটি 10 ​​এর চেয়ে কম হয় তবে 0 টি প্যাডিং হয় না এবং 1204 এর ফলাফল 12.4 হয়। সঠিক ফর্ম্যাটিংয়ের স্ট্রিং "% d।% 02d"
জ্যাকবম্যান

10

কম্পিউটারগুলি ভাসমান-পয়েন্ট সংখ্যাগুলি যেভাবে সঞ্চয় করে তার ফলে এটি ঘটে। তারা ঠিক তাই না। প্রোগ্রামার হিসাবে, আপনার ভাসমান-পয়েন্ট সংখ্যাগুলি পরিচালনা করার ট্রায়ালগুলি এবং দুর্দশাগুলির সাথে নিজেকে পরিচিত করতে এই ভাসমান-পয়েন্ট গাইডটি পড়া উচিত ।


আর্, আমি ঠিক একই জায়গার সাথে লিঙ্ক করে একটি ব্যাখ্যা লিখছিলাম। +1
পোপগুলি

@ লর্ড হা হা, দুঃখিত আমি যেভাবেই হোক স্কিটেড পেয়েছি। :-)
ক্যানস্পাইস

আমি বুঝতে পেরেছি কেন, তবে আমি ভাবছি যে দশমিক স্থানটি সরিয়ে নেওয়ার কোনও সৃজনশীল উপায় আছে কিনা? যেহেতু দ্বিগুণে পরিষ্কারভাবে 12.34 সঞ্চয় করা সম্ভব, এটি কেবল .1 দ্বারা গুণ করা পছন্দ করে না
ব্ল্যাককো

4
যদি দ্বিগুণে 12.34 টি পরিষ্কারভাবে সঞ্চয় করা সম্ভব হয়, তবে আপনি কি মনে করেন না জাভা এটি করেছে? এটা না। আপনাকে কিছু অন্যান্য ডেটাটাইপ (যেমন বিগডিসিমাল) ব্যবহার করতে হবে। এছাড়াও, আপনি কেন এটি লুপের পরিবর্তে 100 দ্বারা ভাগ করবেন না?
ক্যানস্পাইস

দোহ ... হ্যাঁ, এটি দ্বারা 100 ভাগ করে একটি পরিষ্কার 12.34 ফলাফল ... ধন্যবাদ :
পি

9

মজার বিষয় যে বিগডিসিমাল ব্যবহারের জন্য অসংখ্য পোস্ট উল্লেখ করেছেন কিন্তু বিগডিসিমালের উপর ভিত্তি করে সঠিক উত্তর দিতে কেউ বিরক্ত করে? কারণ বিগডিসিমালের সাথেও, আপনি এখনও এই কোড দ্বারা প্রদর্শিত হিসাবে ভুল হতে পারেন

String numstr = "1234";
System.out.println(new BigDecimal(numstr).movePointLeft(2));
System.out.println(new BigDecimal(numstr).multiply(new BigDecimal(0.01)));
System.out.println(new BigDecimal(numstr).multiply(new BigDecimal("0.01")));

এই আউটপুট দেয়

12.34
12.34000000000000025687785232264559454051777720451354980468750
12.34

বিগডিসিমাল কনস্ট্রাক্টর বিশেষভাবে উল্লেখ করেছেন যে স্ট্রিং কনস্ট্রাক্টরকে সংখ্যার কনস্ট্রাক্টরের চেয়ে ব্যবহার করা ভাল। চূড়ান্ত নির্ভুলতা Mathচ্ছিক ম্যাথকন্টেক্সট দ্বারাও প্রভাবিত হয়।

বিগডিসিমাল জাভাদোকের মতে আপনি বিগডিসিমাল তৈরি করা সম্ভব যা ঠিক ০.১ এর সমান, যদি আপনি স্ট্রিং কনস্ট্রাক্টর ব্যবহার করেন।


5

হ্যা এখানে. প্রতিটি দ্বিগুণ ক্রিয়াকলাপের সাথে আপনি নির্ভুলতা হারাতে পারেন তবে প্রতিটি ক্রিয়াকলাপের জন্য নির্ভুলতার পরিমাণ পৃথক হয় এবং ক্রিয়াকলাপের সঠিক ক্রমটি বেছে নিয়ে হ্রাস করা যায়। উদাহরণস্বরূপ সংখ্যার সেটকে গুণিত করার সময়, গুণকের আগে সূচক দ্বারা সেটটি সাজানো ভাল।

সংখ্যা ক্রাঞ্চিংয়ের যে কোনও শালীন বই এটি বর্ণনা করে। উদাহরণস্বরূপ: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

এবং আপনার প্রশ্নের উত্তর দিতে:

গুণনের পরিবর্তে বিভাজন ব্যবহার করুন, আপনি সঠিক ফলাফল পাবেন।

double x = 1234;
for(int i=1;i<=2;i++)
{
  x =  x / 10.0;
}
System.out.println(x);

3

না, জাভা ফ্লোটিং পয়েন্টের ধরণগুলি (প্রকৃতপক্ষে সমস্ত ভাসমান পয়েন্টের ধরণগুলি) আকার এবং নির্ভুলতার মধ্যে একটি বাণিজ্য off যদিও তারা অনেকগুলি কাজের জন্য খুব দরকারী, যদি আপনার স্বেচ্ছাচারিত নির্ভুলতার প্রয়োজন হয়, আপনার ব্যবহার করা উচিত BigDecimal

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.