উল্লেখযোগ্য সংখ্যাগুলির একটি স্বেচ্ছাসেবী সংখ্যায় গোল করে


83

আপনি কীভাবে কোনও সংখ্যাকে (কেবল পূর্ণসংখ্যক> 0) নয় উল্লেখযোগ্য অঙ্কগুলিতে গোল করতে পারেন ?

উদাহরণস্বরূপ, আমি যদি তিনটি উল্লেখযোগ্য অঙ্ককে গোল করতে চাই, তবে আমি এমন একটি সূত্র খুঁজছি যা নিতে পারে:

1,239,451 এবং 1,240,000 ফেরত দিন

12.1257 এবং 12.1 এ ফিরে আসুন

.0681 এবং ফিরে .0681

5 এবং ফিরে 5

স্বাভাবিকভাবেই অ্যালগরিদমটি কেবলমাত্র 3 এর N কে পরিচালনা করতে কঠোর কোডিং করা উচিত নয়, যদিও এটি একটি শুরু হবে।


প্রশ্নটি খুব সাধারণ বলে মনে হচ্ছে। এটি করার জন্য বিভিন্ন প্রোগ্রামিং ভাষার বিভিন্ন স্ট্যান্ডার্ড ফাংশন রয়েছে। প্রকৃতপক্ষে পুনর্নবীকরণের জন্য উপযুক্ত নয়।
জনি ওয়াং

উত্তর:


106

12.100000000000000001 বাগের উত্তরগুলি ছাড়া জাভাতে এখানে একই কোড রয়েছে

আমি পুনরাবৃত্ত কোডটিও সরিয়েছি, powerভাসমান সমস্যাগুলি হয়ে যাওয়ার পরে প্রতিরোধ করতে টাইপ পূর্ণসংখ্যায় পরিবর্তিত n - dহয়ে দীর্ঘ মধ্যবর্তীটিকে আরও পরিষ্কার করে দিয়েছি

একটি সংখ্যক সংখ্যক সংখ্যক সংখ্যক লোককে একটি ছোট সংখ্যার সাথে গুণিত করার কারণে বাগটি হয়েছিল। পরিবর্তে আমি একই আকারের দুটি সংখ্যা বিভক্ত করি।

সম্পাদনা
আরও ত্রুটিযুক্ত। এটির ফলাফলের ফলে 0 এর জন্য চেক যুক্ত করা হয়েছে। ফাংশনটি আসলে নেতিবাচক সংখ্যার সাথে কাজ করে (মূল কোডটি নেতিবাচক সংখ্যাগুলি পরিচালনা করে না কারণ aণাত্মক সংখ্যার লগ একটি জটিল সংখ্যা)

public static double roundToSignificantFigures(double num, int n) {
    if(num == 0) {
        return 0;
    }

    final double d = Math.ceil(Math.log10(num < 0 ? -num: num));
    final int power = n - (int) d;

    final double magnitude = Math.pow(10, power);
    final long shifted = Math.round(num*magnitude);
    return shifted/magnitude;
}

4
আমার উত্তর গ্রহণ করার জন্য ধন্যবাদ। আমি ঠিক বুঝতে পারি আমার উত্তর প্রশ্নের এক বছরেরও বেশি সময় পরে। স্ট্যাকওভারফ্লো এত শীতল হওয়ার এটি একটি কারণ। আপনি দরকারী তথ্য খুঁজে পেতে পারেন!
পাইরোলিস্টিকাল

4
নোট করুন যে এটি গোল সীমাটির কাছাকাছি মানের জন্য কিছুটা ব্যর্থ হতে পারে। উদাহরণস্বরূপ উদাহরণস্বরূপ 1.255 থেকে 3 টি উল্লেখযোগ্য সংখ্যার 1.26 ফিরতে হবে তবে 1.25 প্রদান করবে 25 কারণ 1.255 * 100.0 হল 125.499999 ... তবে ডাবলসের সাথে কাজ করার সময় এটি প্রত্যাশিত হতে পারে
cquezel

বাহ, আমি জানি এটি পুরানো, তবে আমি এটি ব্যবহারের চেষ্টা করছি। আমার কাছে একটি ফ্লোট রয়েছে যা আমি 3 টি গুরুত্বপূর্ণ ব্যক্তিকে প্রদর্শন করতে চাই। যদি ভাসমানটির মান 1.0 হয় তবে আমি আপনার পদ্ধতিটি কল করি তবে এটি এখনও 1.0 হিসাবে ফিরে আসে, এমনকি আমি যদি ডাবল হিসাবে ভাসাটি ফেলে দিই। আমি এটি 1 হিসাবে ফিরে আসতে চান কোন ধারণা?
স্টিভ ডাব্লু

4
এই জাভা স্নিপেটটি অফিসিয়াল অ্যান্ড্রয়েড উদাহরণে শেষ হয় android.googlesource.com/platform/development/+/fcf4286/sams/…
কৌতূহলী স্যাম

4
উপযুক্ত না. নাম্বার জন্য -7999999.999999992 এবং এন = 2 রিটার্ন -7999999.999999999 তবে -8000000 হওয়া উচিত।
ডানকান কলভার্ট

16

এখানে একটি সংক্ষিপ্ত এবং মিষ্টি জাভাস্ক্রিপ্ট বাস্তবায়ন:

function sigFigs(n, sig) {
    var mult = Math.pow(10, sig - Math.floor(Math.log(n) / Math.LN10) - 1);
    return Math.round(n * mult) / mult;
}

alert(sigFigs(1234567, 3)); // Gives 1230000
alert(sigFigs(0.06805, 3)); // Gives 0.0681
alert(sigFigs(5, 3)); // Gives 5

4
ভাল উত্তর Ates। সম্ভবত 0 এ ফিরে আসার জন্য একটি ট্রিগার যুক্ত করুন n==0:)
স্কিরিস

এর Math.log(n) / Math.LN10চেয়ে কি করার কারণ আছে Math.log10(n)?
লি

4
@ লিভ বিকাশকারী.মোজিলা.আর.ইন- ইউএস / ডকস / ওয়েবে / জাভা স্ক্রিপ্ট / রেফারেন্স / "" এটি একটি নতুন প্রযুক্তি, ইসমাস্ক্রিপ্ট ২০১৫ (ইএস)) মানের অংশ "" সুতরাং, মূলত, সামঞ্জস্য সমস্যা।
এটস গোরাল 3

আমি কি কিছু মিস করছি, বা এই উত্তরটি কি ধরে নিয়েছে Math.floor(x) == Math.ceil(x) - 1? কারণ এটি কখন xপূর্ণসংখ্যা হয় না । আমি মনে করি powফাংশনের দ্বিতীয় যুক্তিটি হওয়া উচিত sig - Math.ceil(Math.log(n) / Math.LN10)(বা কেবল ব্যবহার করুন Math.log10)
পল

15

সারসংক্ষেপ:

double roundit(double num, double N)
{
    double d = log10(num);
    double power;
    if (num > 0)
    {
        d = ceil(d);
        power = -(d-N);
    }
    else
    {
        d = floor(d); 
        power = -(d-N);
    }

    return (int)(num * pow(10.0, power) + 0.5) * pow(10.0, -power);
}

সুতরাং আপনাকে প্রথম অ-শূন্য অঙ্কের দশমিক স্থান খুঁজে বের করতে হবে, তারপরে পরবর্তী এন -1 অঙ্কগুলি সংরক্ষণ করুন, তারপরে বাকীগুলির উপর ভিত্তি করে নবম সংখ্যাটি বৃত্তাকার করুন।

আমরা প্রথমে লগ ব্যবহার করতে পারি।

log 1239451 = 6.09
log 12.1257 = 1.08
log 0.0681  = -1.16

সুতরাং সংখ্যার জন্য> 0, লগের সিলটি নিন। <0 সংখ্যার জন্য, লগের ফ্লোর নিন।

এখন আমাদের সংখ্যাটি রয়েছে d: প্রথম ক্ষেত্রে 7, 2 য় 2, 3 য় -2।

আমাদের (d-N)তম সংখ্যাটি গোল করতে হবে । কিছুটা এইরকম:

double roundedrest = num * pow(10, -(d-N));

pow(1239451, -4) = 123.9451
pow(12.1257, 1)  = 121.257
pow(0.0681, 4)   = 681

তারপরে স্ট্যান্ডার্ড রাউন্ডিং জিনিসটি করুন:

roundedrest = (int)(roundedrest + 0.5);

এবং পাও পূর্বাবস্থায় ফেরা।

roundednum = pow(roundedrest, -(power))

যেখানে শক্তি উপরের শক্তি গণনা করা হয়।


নির্ভুলতা সম্পর্কে: পাইরোলিস্টিকালের উত্তর সত্যিকারের ফলাফলের কাছাকাছি। তবে মনে রাখবেন যে আপনি কোনও অবস্থাতেই 12.1 উপস্থাপন করতে পারবেন না। যদি আপনি উত্তরগুলি নিম্নরূপে মুদ্রণ করেন:

System.out.println(new BigDecimal(n));

উত্তরগুলি হ'ল:

Pyro's: 12.0999999999999996447286321199499070644378662109375
Mine: 12.10000000000000142108547152020037174224853515625
Printing 12.1 directly: 12.0999999999999996447286321199499070644378662109375

সুতরাং, পাইরো এর উত্তর ব্যবহার করুন!


4
এই অ্যালগরিদম ভাসমান পয়েন্ট ত্রুটিগুলির প্রবণ বলে মনে হচ্ছে। জাভাস্ক্রিপ্টের সাথে প্রয়োগ করা হলে, আমি পেয়েছি: 0.06805 -> 0.068100000000000011 এবং 12.1 -> 12.1000000000000011
এটেস

12.1 নিজে থেকে ভাসমান পয়েন্টটি ব্যবহার করে সঠিকভাবে প্রতিনিধিত্ব করা যায় না - এটি এই অ্যালগরিদমের ফলাফল নয়।
ক্লাদিউ

4
জাভাতে এই কোডটি 12.10000000000000001 উত্পাদন করে এবং এটি 64-বিট ডাবল ব্যবহার করছে যা 12.1 ঠিক উপস্থাপন করতে পারে।
পাইরোলিস্টিকাল

4
এটি 64 বিট বা 128 বিট হলেও গুরুত্বপূর্ণ নয় doesn't 2
ক্লাদিউ

4
যারা চিমন করছে তাদের জন্য মূলত পাইরোলিস্টিকাল এর উত্তর আমার চেয়ে আরও সুনির্দিষ্ট যাতে ভাসমান পয়েন্ট নম্বর মুদ্রণের অ্যালগোরিদম '12 .100000000000001 'এর পরিবর্তে '12 .1' মুদ্রণ করে। তার উত্তরটি আরও ভাল, এমনকি আমি প্রযুক্তিগতভাবে সঠিক ছিলাম যে আপনি '12 .১ 'উপস্থাপন করতে পারবেন না।
ক্লাদিউ

10

"সংক্ষিপ্ত এবং মিষ্টি" জাভাস্ক্রিপ্ট বাস্তবায়ন নয়

Number(n).toPrecision(sig)

যেমন

alert(Number(12345).toPrecision(3)

?

দুঃখিত, আমি এখানে আকর্ষণীয় নই, এটি কেবলমাত্র ক্লাউডিয়ু থেকে "রাউন্ডিট" ফাংশন এবং জাভাস্ক্রিপ্টে .toPrecision ব্যবহার করে আমাকে বিভিন্ন ফলাফল দেয় তবে কেবলমাত্র শেষ অঙ্কের গোল করে।

জাভাস্ক্রিপ্ট:

Number(8.14301).toPrecision(4) == 8.143

.NET

roundit(8.14301,4) == 8.144

4
Number(814301).toPrecision(4) == "8.143e+5"। আপনি যদি ব্যবহারকারীদের কাছে এটি দেখান তবে সাধারণত আপনি যা চান তা তা নয়।
জাজ

খুব সত্য জোশ হ্যাঁ, আমি সাধারণত সুপারিশ করবো। কেবলমাত্র দশমিক সংখ্যার জন্য প্রবর্তন () এবং স্বীকৃত উত্তর (সম্পাদনা সহ) আপনার পৃথক প্রয়োজনীয়তা অনুসারে ব্যবহার / পর্যালোচনা করা উচিত।
জাস্টিন উইগনল

8

পাইরোলিস্টিকালের (খুব সুন্দর!) সমাধানে এখনও একটি সমস্যা রয়েছে। জাভাতে সর্বাধিক ডাবল মান 10 ^ 308 এর ক্রম হয়, সর্বনিম্ন মান 10 ^ -324 এর ক্রম হয়। সুতরাং, roundToSignificantFiguresদশটির কয়েকটি পাওয়ারের মধ্যে এমন কিছুতে ফাংশনটি প্রয়োগ করার সময় আপনি সমস্যার মধ্যে পড়তে পারেন Double.MIN_VALUE। উদাহরণস্বরূপ, আপনি যখন কল করবেন

roundToSignificantFigures(1.234E-310, 3);

তারপরে ভেরিয়েবলের powerমান 3 - (-309) = 312 হবে quently ফলস্বরূপ, ভেরিয়েবলটি magnitudeহয়ে যাবে Infinityএবং এর পরে সমস্ত আবর্জনা। ভাগ্যক্রমে, এটি একটি দুর্গম সমস্যা নয়: এটি কেবলমাত্র ফ্যাক্টর magnitude যা উপচে পড়া। প্রকৃতপক্ষে যা গুরুত্বপূর্ণ তা হল পণ্য num * magnitude এবং এটি উপচে পড়ে না। এর সমাধান করার একটি উপায় হ'ল গুণকে magintudeদুটি ধাপে বিভক্ত করা:


 public static double roundToNumberOfSignificantDigits(double num, int n) {

    final double maxPowerOfTen = Math.floor(Math.log10(Double.MAX_VALUE));

    if(num == 0) {
        return 0;
    }

    final double d = Math.ceil(Math.log10(num < 0 ? -num: num));
    final int power = n - (int) d;

    double firstMagnitudeFactor = 1.0;
    double secondMagnitudeFactor = 1.0;
    if (power > maxPowerOfTen) {
        firstMagnitudeFactor = Math.pow(10.0, maxPowerOfTen);
        secondMagnitudeFactor = Math.pow(10.0, (double) power - maxPowerOfTen);
    } else {
        firstMagnitudeFactor = Math.pow(10.0, (double) power);
    }

    double toBeRounded = num * firstMagnitudeFactor;
    toBeRounded *= secondMagnitudeFactor;

    final long shifted = Math.round(toBeRounded);
    double rounded = ((double) shifted) / firstMagnitudeFactor;
    rounded /= secondMagnitudeFactor;
    return rounded;
}


6

এই জাভা সমাধান সম্পর্কে:

ডাবল রাউন্ড টু সিগিনিফিক্যান্ট ফিগার (ডাবল নাম্বার, প্রাক নির্ভুলতা) {
 নতুন বিগডিসিমাল (নম্বর) ফেরান
            .উন্ড (নতুন ম্যাথকন্টেক্সট (যথার্থতা, রাউন্ডিংমড। HALF_EVEN))
            .doubleValue (); 
}

3

এটসের জাভাস্ক্রিপ্টের একটি সংশোধিত সংস্করণ এখানে negativeণাত্মক সংখ্যাগুলি পরিচালনা করে।

function sigFigs(n, sig) {
    if ( n === 0 )
        return 0
    var mult = Math.pow(10,
        sig - Math.floor(Math.log(n < 0 ? -n: n) / Math.LN10) - 1);
    return Math.round(n * mult) / mult;
 }

2

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

আপনি যদি কেবল এটি মুদ্রণ করতে চান তবে এটি।

public String toSignificantFiguresString(BigDecimal bd, int significantFigures){
    return String.format("%."+significantFigures+"G", bd);
}

আপনি যদি এটি রূপান্তর করতে চান তবে এটি:

public BigDecimal toSignificantFigures(BigDecimal bd, int significantFigures){
    String s = String.format("%."+significantFigures+"G", bd);
    BigDecimal result = new BigDecimal(s);
    return result;
}

কর্মের ক্ষেত্রে এটির উদাহরণ এখানে:

BigDecimal bd = toSignificantFigures(BigDecimal.valueOf(0.0681), 2);

এটি বৈজ্ঞানিক স্বরলিপিতে "বড়" সংখ্যা প্রদর্শন করবে, যেমন 15 কে 1.5e04 হিসাবে।
ম্যাট

2

জাভাস্ক্রিপ্ট:

Number( my_number.toPrecision(3) );

Numberফাংশন ফর্ম আউটপুট পরিবর্তন হবে "8.143e+5"থেকে "814300"


1

আপনি হাত দিয়ে যেভাবে করতে চান কেবল কোড করার চেষ্টা করেছেন?

  1. সংখ্যাটিকে একটি স্ট্রিতে রূপান্তর করুন
  2. স্ট্রিংয়ের শুরুতে, অঙ্কগুলি গণনা করুন - শীর্ষস্থানীয় শূন্যগুলি তাৎপর্যপূর্ণ নয়, সমস্ত কিছু।
  3. আপনি যখন "নবম" অঙ্কে পৌঁছবেন, পরবর্তী অঙ্কে এগিয়ে উঁকি দিন এবং যদি এটি 5 বা তার বেশি হয় তবে গোল করে নিন।
  4. শূন্যের সাহায্যে চলমান সমস্ত সংখ্যার প্রতিস্থাপন করুন।

1

[সংশোধন, 2009-10-26]

মূলত, এন উল্লেখযোগ্য ভগ্নাংশের সংখ্যাগুলির জন্য:

10 সংখ্যাটি 10 এন দ্বারা গুণান
0.5 0.5% যোগ করুন
ভগ্নাংশের সংখ্যাগুলি কেটে ফেলুন (অর্থাত্ ফলাফলটি পূর্ণসংখ্যায় কেটে ফেলুন)
10 10 এন দ্বারা ভাগ করুন

এন উল্লেখযোগ্য ইন্টিগ্রাল (অ-ভগ্নাংশ) সংখ্যার জন্য:

10 সংখ্যাটি 10 এন দ্বারা ভাগ
করুন 0.5 0.5
• যুক্ত করুন ভগ্নাংশের সংখ্যাগুলি কেটে ফেলুন (অর্থাত্ ফলাফলটি একটি পূর্ণসংখ্যায় কেটে ফেলুন)
10 10 এন দ্বারা গুণ করুন

আপনি এটি যে কোনও ক্যালকুলেটরটিতে করতে পারেন, উদাহরণস্বরূপ, এতে একটি "আইএনটি" (পূর্ণসংখ্যা কাটা) অপারেটর রয়েছে।


নাহ। প্রশ্নটি আবার পড়ুন। আপনার অ্যালগরিদম ব্যবহার করে 3 টি সিগ ডুমুর সহ 1239451 ভুলভাবে ফলন করবে 123951
পাইরোলিস্টিকাল

হ্যাঁ, আমি অঙ্কের একটি ভগ্নাংশের সংখ্যার (দশমিক পয়েন্টের ডানদিকে) বনাম অঙ্কের একটি অবিচ্ছেদ্য সংখ্যা (বাম দিকে) এর মধ্যে পার্থক্য করার জন্য এটি সংশোধন করেছি ।
ডেভিড আর ট্রাইবল

1
/**
 * Set Significant Digits.
 * @param value value
 * @param digits digits
 * @return
 */
public static BigDecimal setSignificantDigits(BigDecimal value, int digits) {
    //# Start with the leftmost non-zero digit (e.g. the "1" in 1200, or the "2" in 0.0256).
    //# Keep n digits. Replace the rest with zeros.
    //# Round up by one if appropriate.
    int p = value.precision();
    int s = value.scale();
    if (p < digits) {
        value = value.setScale(s + digits - p); //, RoundingMode.HALF_UP
    }
    value = value.movePointRight(s).movePointLeft(p - digits).setScale(0, RoundingMode.HALF_UP)
        .movePointRight(p - digits).movePointLeft(s);
    s = (s > (p - digits)) ? (s - (p - digits)) : 0;
    return value.setScale(s);
}

1

ভিজ্যুয়াল বেসিক.এনইটি-তে পাইরোলিস্টিকালের (বর্তমানে শীর্ষের উত্তর) কোডটি এখানে রয়েছে, কারও যদি এটির প্রয়োজন হয়:

Public Shared Function roundToSignificantDigits(ByVal num As Double, ByVal n As Integer) As Double
    If (num = 0) Then
        Return 0
    End If

    Dim d As Double = Math.Ceiling(Math.Log10(If(num < 0, -num, num)))
    Dim power As Integer = n - CInt(d)
    Dim magnitude As Double = Math.Pow(10, power)
    Dim shifted As Double = Math.Round(num * magnitude)
    Return shifted / magnitude
End Function

0

এটি একটি যা আমি ভিবিতে নিয়ে এসেছি:

Function SF(n As Double, SigFigs As Integer)
    Dim l As Integer = n.ToString.Length
    n = n / 10 ^ (l - SigFigs)
    n = Math.Round(n)
    n = n * 10 ^ (l - SigFigs)
    Return n
End Function


0

math.Round()গোতে আমার এটি দরকার ছিল যা গো স্ট্যান্ডার্ড লাইব্রেরির অভাব (go1.10 এর আগে) দ্বারা কিছুটা জটিল হয়েছিল । সুতরাং আমি খুব চাবুক ছিল। পাইরোলিস্টিকালের দুর্দান্ত উত্তরের এখানে আমার অনুবাদ :

// TODO: replace in go1.10 with math.Round()
func round(x float64) float64 {
    return float64(int64(x + 0.5))
}

// SignificantDigits rounds a float64 to digits significant digits.
// Translated from Java at https://stackoverflow.com/a/1581007/1068283
func SignificantDigits(x float64, digits int) float64 {
    if x == 0 {
        return 0
    }

    power := digits - int(math.Ceil(math.Log10(math.Abs(x))))
    magnitude := math.Pow(10, float64(power))
    shifted := round(x * magnitude)
    return shifted / magnitude
}

এটি একটি রহস্য নেমে গেছে! তবে আমি এতে কোনও ত্রুটি বা সমস্যা খুঁজে পাচ্ছি না। এখানে কি হচ্ছে?
মাইকেল হ্যাম্পটন

0

আপনি কেবলমাত্র ফ্লোটটোএসটিএফ ব্যবহার করে 10 ইত্যাদির শক্তি দিয়ে এই সমস্ত গণনা করা এড়াতে পারবেন।

ফ্লোটটোএসআরএফ আপনাকে আউটপুট মানটিতে (যা একটি স্ট্রিং হবে) যথার্থতা (উল্লেখযোগ্য পরিসংখ্যানগুলির সংখ্যা) চয়ন করতে দেয় (অন্যান্য জিনিসের মধ্যে)। অবশ্যই, আপনি তারপরে ভাসমান হিসাবে আপনার বৃত্তাকার মান পেতে এটিতে স্ট্রিটোফ্লোট প্রয়োগ করতে পারেন।

এখানে দেখো:

http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/SysUtils_FloatToStrF@Extended@TFloat Format@Integer@Integer.html


-1
public static double roundToSignificantDigits(double num, int n) {
    return Double.parseDouble(new java.util.Formatter().format("%." + (n - 1) + "e", num).toString());
}

এই কোডটি ইনবিল্ট ফর্ম্যাটিং ফাংশনটি ব্যবহার করে যা একটি বৃত্তাকার ফাংশনে পরিণত হয়

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