পারলে আপনি কীভাবে একটি ভাসমান পয়েন্ট সংখ্যাটি গোল করবেন?


174

আমি কীভাবে নিকটতম পূর্ণসংখ্যার দশমিক সংখ্যার (ভাসমান পয়েন্ট) গোল করতে পারি?

যেমন

1.2 = 1
1.7 = 2

উত্তর:


196

আউটপুট perldoc -q round

পারেলের কি কোনও গোল () ফাংশন আছে? সিল () এবং মেঝে () সম্পর্কে কী? ট্রিগ ফাংশন?

মনে রাখবেন যে int()নিছক দিকে কেটে গেছে 0। নির্দিষ্ট সংখ্যার গোলাকৃতির জন্য sprintf()বা printf()সাধারণত সবচেয়ে সহজ রুট।

    printf("%.3f", 3.1415926535);       # prints 3.142

POSIXমডিউল (আদর্শ পার্ল বন্টন অংশ) কার্যকরী ceil(), floor()এবং অন্যান্য গাণিতিক এবং ত্রিকোণমিতিক ফাংশন একটি সংখ্যা।

    use POSIX;
    $ceil   = ceil(3.5);                        # 4
    $floor  = floor(3.5);                       # 3

5.000 থেকে 5.003 পার্লগুলিতে, Math::Complex মডিউলে ত্রিকোণমিতি করা হয়েছিল । 5.004 সহ, Math::Trigমডিউলটি (স্ট্যান্ডার্ড পার্ল বিতরণের অংশ) ত্রিকোনোমেট্রিক ফাংশনগুলি প্রয়োগ করে। অভ্যন্তরীণভাবে এটি Math::Complexমডিউলটি ব্যবহার করে এবং কিছু ফাংশন প্রকৃত অক্ষ থেকে জটিল প্লেনে বের হয়ে যেতে পারে, উদাহরণস্বরূপ 2 এর বিপরীত সাইন।

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

কেন তা দেখার জন্য, লক্ষ্য করুন যে কীভাবে আপনার অর্ধ-পয়েন্ট বিকল্পে এখনও সমস্যা থাকবে:

    for ($i = 0; $i < 1.01; $i += 0.05) { printf "%.1f ",$i}

    0.0 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.4 0.5 0.5 0.6 0.7 0.7
    0.8 0.8 0.9 0.9 1.0 1.0

পার্লকে দোষ দিবেন না। এটি সি এর মতোই রয়েছে আইইইই বলছে আমাদের এটি করতে হবে। পার্ল সংখ্যা যাদের পরম মানগুলি 2**31(32 বিট মেশিনে) এর অধীনে পূর্ণসংখ্যা হয় গাণিতিক পূর্ণসংখ্যার মতো কাজ করবে। অন্যান্য সংখ্যা গ্যারান্টিযুক্ত হয় না।


17
^ থরিমা, কেন সিল অবমূল্যায়ন হবে? আমি যতদূর জানি পসিক্স বা পার্লে এটি অবহেলা করা হয়নি। তথ্যসূত্র প্রয়োজন!
স্যাম ওয়াটকিন্স

3
@ শিক্ষানবিশরা, printfআপনি যদি কোনও পরিবর্তনশীলের ফলাফল চান তা ব্যবহার করার চেষ্টা করবেন না , ব্যবহার করুন sprintf... আশা করি এটি আপনাকে কিছুটা ডিবাগিং-সময় সাশ্রয় করবে :
পি

আমি int()পিডিএল ব্যবহার করতে পারি ?
কনকাউট

1
পসিক্স ব্যবহার করুন; <br/> $ x = ($ x - তল ($ x)> = .5)? সিল ($ x): তল ($ x);
জোসেফ আর্জেনিও

136

অর্ধপথ চিহ্ন সম্পর্কে জটিল উত্তরগুলির সাথে একমত না হওয়া এবং আরও সাধারণ (এবং সম্ভবত তুচ্ছ) ব্যবহারের ক্ষেত্রে:

my $rounded = int($float + 0.5);

হালনাগাদ

যদি আপনার $floatপক্ষে এটি নেতিবাচক হওয়া সম্ভব হয় তবে নীচের ভিন্নতা সঠিক ফলাফল আনবে:

my $rounded = int($float + $float/abs($float*2 || 1));

এই গণনার সাহায্যে -1.4 গোল করে -1, এবং -1.6 থেকে -2 হয় এবং শূন্যটি বিস্ফোরিত হবে না।


4
... তবে এটি নেতিবাচক সংখ্যায় ব্যর্থ: আরও ভাল স্প্রিন্টফ
অ্যালসান্দ্রো

2
আহ না, তা হয় না। Aণাত্মক সংখ্যাকে গোল করা আপনাকে আরও বেশি দূরে নয়, শূন্যের কাছাকাছি নিয়ে যায়। আজকাল তারা স্কুলে কী পড়ায়?
RET

6
@ আরইটি হ্যাঁ, এটি নেতিবাচক সংখ্যাগুলির সাথে ব্যর্থ হয়। এই পদ্ধতিতে with ভাসা = -1.4 ফলাফল 0। তারা আমার স্কুলে যা শিখিয়েছিল তা নয়। মনে রাখবেন যে int () শূন্যের দিকে ছাঁটা হয়েছে।
ফিশিনিয়ার

4
@ ফিশিনিয়ার আপনি সঠিক, এবং আমি যথাযথভাবে অনুশাসন করছি। তবে আমি 'তুচ্ছ ব্যবহারের ক্ষেত্রে' বলেছিলাম। আমার উত্তর সংশোধন করা হয়েছে।
RET

1
নোট করুন যে এটি ফ্লোট = 0, এটি ব্যর্থ হবে :-)
মাদুর

74

আপনি ম্যাথ :: রাউন্ডের মতো মডিউল ব্যবহার করতে পারেন :

use Math::Round;
my $rounded = round( $float );

অথবা আপনি এটি অশোধিত উপায়ে করতে পারেন:

my $rounded = sprintf "%.0f", $float;

46

আপনি যদি প্রিন্টফ বা স্প্রিন্টফ ব্যবহার করার সিদ্ধান্ত নেন তবে নোট করুন যে তারা রাউন্ড অর্ধেকটি এমনকি পদ্ধতিতে ব্যবহার করে ।

foreach my $i ( 0.5, 1.5, 2.5, 3.5 ) {
    printf "$i -> %.0f\n", $i;
}
__END__
0.5 -> 0
1.5 -> 2
2.5 -> 2
3.5 -> 4

এই বিষয়টি চিহ্নিত করার জন্য ধন্যবাদ. আরও স্পষ্টভাবে, পদ্ধতির নাম 'রাউন্ড হাফ টু ইভেন'।
জিন ভিনসেন্ট

মুদ্রণ বা স্প্রিন্টফের উল্লেখ থাকা সমস্ত উত্তরগুলির মধ্যে এটি উল্লেখ করা উচিত।
insaner

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

আসলে, এটি ওএস নির্ভর! উইন্ডোজে এটি শূন্য থেকে অর্ধেক দূরে গোল করবে এবং ইউনিক্সের মতো অর্ধেক পর্যন্ত গোল হয়ে যাবে: এক্সপ্লোরিংবাইনারি.
com/…

9

পার্ল্ডোক / পারফ্যালাক দেখুন :

মনে রাখবেন যে int()কেবলমাত্র 0 টির দিকে ছাঁটাই হয় নির্দিষ্ট নির্দিষ্ট সংখ্যার চারদিকে যাওয়ার জন্য, sprintf()বা printf()সাধারণত সবচেয়ে সহজতম পথ।

 printf("%.3f",3.1415926535);
 # prints 3.142

POSIXমডিউল (আদর্শ পার্ল বন্টন অংশ) কার্যকরী ceil(), floor()এবং অন্যান্য গাণিতিক এবং ত্রিকোণমিতিক ফাংশন একটি সংখ্যা।

use POSIX;
$ceil  = ceil(3.5); # 4
$floor = floor(3.5); # 3

5.000 থেকে 5.003 পার্লগুলিতে, Math::Complexমডিউলে ত্রিকোণমিতি করা হয়েছিল ।

5.004 সহ, Math::Trigমডিউলটি (স্ট্যান্ডার্ড পার্ল বিতরণের অংশ)> ত্রিকোণমিতিক ফাংশনগুলি প্রয়োগ করে।

অভ্যন্তরীণভাবে এটি Math::Complexমডিউলটি ব্যবহার করে এবং কিছু ফাংশন প্রকৃত অক্ষ থেকে জটিল প্লেনে বের হয়ে যেতে পারে, উদাহরণস্বরূপ 2 এর বিপরীত সাইন।

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

কেন তা দেখার জন্য, লক্ষ্য করুন যে কীভাবে আপনার অর্ধ-পয়েন্ট বিকল্পে এখনও সমস্যা থাকবে:

for ($i = 0; $i < 1.01; $i += 0.05)
{
   printf "%.1f ",$i
}

0.0 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.4 0.5 0.5 0.6 0.7 0.7 0.8 0.8 0.9 0.9 1.0 1.0

পার্লকে দোষ দিবেন না। এটি সি এর মতোই রয়েছে আইইইই বলছে আমাদের এটি করতে হবে। পারল সংখ্যা যাদের পরম মান 2 ** 31 (32 বিট মেশিনে) এর অধীনে পূর্ণসংখ্যা হয় তা গাণিতিক পূর্ণসংখ্যার মতো কার্যকরভাবে কাজ করবে। অন্যান্য সংখ্যা গ্যারান্টিযুক্ত হয় না।


3

আপনার কোনও বাহ্যিক মডিউল দরকার নেই।

$x[0] = 1.2;
$x[1] = 1.7;

foreach (@x){
  print $_.' = '.( ( ($_-int($_))<0.5) ? int($_) : int($_)+1 );
  print "\n";
}

আমি আপনার বক্তব্য মিস করছি, তবে আমি ভেবেছিলাম এটি একই কাজটি করার জন্য আরও পরিষ্কার উপায় way

এটি যা করে তা হ'ল উপাদানটির প্রতিটি ধনাত্মক সংখ্যার মধ্য দিয়ে যাওয়া, আপনি উল্লিখিত বিন্যাসে নম্বর এবং বৃত্তাকার পূর্ণসংখ্যা মুদ্রণ করা। কোডটি দশমিকের ভিত্তিতে স্বতন্ত্র বৃত্তাকার ধনাত্মক পূর্ণসংখ্যাকে সম্মতি দেয়। int ($ _) মূলত সংখ্যাকে গোল করে ডাউন করে তাই ( int -int ($ )) দশমিকগুলি ক্যাপচার করে। দশমিকগুলি যদি (সংজ্ঞা অনুসারে) কঠোরভাবে 0.5 এর চেয়ে কম হয় তবে সংখ্যাটি বৃত্তাকার ডাউন করুন। যদি না হয়, 1 যোগ করে রাউন্ড-আপ করুন।


1
আরটিএলের উত্তরের মতো সমানভাবে কাজ করলে কেন আবার একটি জটিল প্রশ্নের উত্তর দিয়ে একটি প্রাচীন প্রশ্নের উত্তর দিন।
জোয়েল বার্গার

1
এটি সত্যই জটিল নয়, আর আরইটির উত্তরে গণিতের একগুচ্ছ জড়িত রয়েছে যে ক) তাত্ত্বিকভাবে অতিরিক্ত প্রবাহ ঝুঁকিপূর্ণ, খ) আরও বেশি সময় নেয়, এবং গ) অযথা আপনার চূড়ান্ত মানটির জন্য আরও এফপি অনবোধের পরিচয় দেয়। অপেক্ষা করুন, কোনটি আবার জটিল? ;)
cptstubing06

2

নিম্নলিখিতটি একটি নির্দিষ্ট দশমিক অবস্থানে ধনাত্মক বা নেতিবাচক সংখ্যাকে গোল করবে:

sub round ()
{
    my ($x, $pow10) = @_;
    my $a = 10 ** $pow10;

    return (int($x / $a + (($x < 0) ? -0.5 : 0.5)) * $a);
}

1

নীচে মানগুলি যোগ করার জন্য পাঁচটি ভিন্ন উপায়ের একটি নমুনা দেওয়া হল। প্রথমটি হ'ল সংক্ষেপটি সম্পাদন করার একটি নির্দোষ উপায় (এবং ব্যর্থ হয়)। দ্বিতীয় চেষ্টাটি ব্যবহার করার চেষ্টা sprintf()করলেও এটি ব্যর্থ হয়। sprintf()চূড়ান্ত দুটি (চতুর্থ এবং 5 তম) ব্যবহারের সময় তৃতীয়টি সফলভাবে ব্যবহার করে floor($value + 0.5)

 use strict;
 use warnings;
 use POSIX;

 my @values = (26.67,62.51,62.51,62.51,68.82,79.39,79.39);
 my $total1 = 0.00;
 my $total2 = 0;
 my $total3 = 0;
 my $total4 = 0.00;
 my $total5 = 0;
 my $value1;
 my $value2;
 my $value3;
 my $value4;
 my $value5;

 foreach $value1 (@values)
 {
      $value2 = $value1;
      $value3 = $value1;
      $value4 = $value1;
      $value5 = $value1;

      $total1 += $value1;

      $total2 += sprintf('%d', $value2 * 100);

      $value3 = sprintf('%1.2f', $value3);
      $value3 =~ s/\.//;
      $total3 += $value3;

      $total4 += $value4;

      $total5 += floor(($value5 * 100.0) + 0.5);
 }

 $total1 *= 100;
 $total4 = floor(($total4 * 100.0) + 0.5);

 print '$total1: '.sprintf('%011d', $total1)."\n";
 print '$total2: '.sprintf('%011d', $total2)."\n";
 print '$total3: '.sprintf('%011d', $total3)."\n";
 print '$total4: '.sprintf('%011d', $total4)."\n";
 print '$total5: '.sprintf('%011d', $total5)."\n";

 exit(0);

 #$total1: 00000044179
 #$total2: 00000044179
 #$total3: 00000044180
 #$total4: 00000044180
 #$total5: 00000044180

নোট যেটির উপর নির্ভরতা অপসারণ floor($value + 0.5)করতে প্রতিস্থাপন করা যেতে পারে ।int($value + 0.5)POSIX


1

নেতিবাচক সংখ্যাগুলি এমন কিছু কৌতুক যুক্ত করতে পারে যা সম্পর্কে লোকদের সচেতন হওয়া দরকার।

printfস্টাইলের পদ্ধতিগুলি আমাদের সঠিক সংখ্যা দেয় তবে সেগুলি কিছু বিজোড় প্রদর্শন করতে পারে। আমরা আবিষ্কার করেছি যে এই পদ্ধতিটি (আমার মতে, বোকামির সাথে) -এটি একটি হওয়া উচিত এবং না করা উচিত কিনা তা একটি চিহ্ন দেয় uts উদাহরণস্বরূপ, -0.01 একটি দশমিক স্থানে গোল করে কেবল 0-এর পরিবর্তে 0-0.0 প্রদান করে, আপনি যদি printfশৈলীর পদ্ধতির সাথে কাজ করতে চলেছেন এবং আপনি জানেন যে আপনি কোনও দশমিক চান না, ব্যবহার করুন %dএবং না %f(যখন আপনার দশমিকের প্রয়োজন হবে, যখন এটি ডিসপ্লে উইনকি হয়ে যায়)।

যদিও এটি সঠিক এবং গণিতের জন্য কোনও বড় বিষয় নয়, প্রদর্শনের জন্য এটি "-0.0" এর মতো কিছু দেখানো অদ্ভুত দেখাচ্ছে।

অভ্যন্তরীণ পদ্ধতির জন্য, negativeণাত্মক সংখ্যাগুলি ফলস্বরূপ আপনি যা চান তা পরিবর্তন করতে পারে (যদিও কিছু যুক্তি রয়েছে যা সেগুলি সঠিক হতে পারে)।

int + 0.5, -Negative সংখ্যার বাস্তব সমস্যা ঘটায় যদি না আপনি এটা যে ভাবে কাজ করতে চান, কিন্তু আমি কল্পনা অধিকাংশ লোক না। -০.৯ সম্ভবতঃ -১ এর মধ্যে হওয়া উচিত, ০ নয় পরিবর্তন (এটি স্পষ্টতই পুরো সংখ্যা ফিরে পেতে কাজ করে:

my $var = -9.1;
my $tmpRounded = int( abs($var) + 0.5));
my $finalRounded = $var >= 0 ? 0 + $tmpRounded : 0 - $tmpRounded;

0

স্প্রিন্টফের জন্য আমার সমাধান

if ($value =~ m/\d\..*5$/){
    $format =~ /.*(\d)f$/;
    if (defined $1){
       my $coef = "0." . "0" x $1 . "05";    
            $value = $value + $coef;    
    }
}

$value = sprintf( "$format", $value );

0

আপনি যদি কেবলমাত্র পুরো ভাসমান পয়েন্ট সংখ্যা (যেমন 12347.9999 বা 54321.0001) এর মধ্যে একটি পূর্ণসংখ্যার মান পাওয়ার সাথে সম্পর্কিত হন তবে এই পদ্ধতিটি (উপরে নেওয়া এবং সংশোধিত) কৌশলটি করবে:

my $rounded = floor($float + 0.1); 

0

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

sub asDollars($) {
  my ($cost) = @_;
  my $rv = 0;

  my $negative = 0;
  if ($cost =~ /^-/) {
    $negative = 1;
    $cost =~ s/^-//;
  }

  my @cost = split(/\./, $cost);

  # let's get the first 3 digits of $cost[1]
  my ($digit1, $digit2, $digit3) = split("", $cost[1]);
  # now, is $digit3 >= 5?
  # if yes, plus one to $digit2.
  # is $digit2 > 9 now?
  # if yes, $digit2 = 0, $digit1++
  # is $digit1 > 9 now??
  # if yes, $digit1 = 0, $cost[0]++
  if ($digit3 >= 5) {
    $digit3 = 0;
    $digit2++;
    if ($digit2 > 9) {
      $digit2 = 0;
      $digit1++;
      if ($digit1 > 9) {
        $digit1 = 0;
        $cost[0]++;
      }
    }
  }
  $cost[1] = $digit1 . $digit2;
  if ($digit1 ne "0" and $cost[1] < 10) { $cost[1] .= "0"; }

  # and pretty up the left of decimal
  if ($cost[0] > 999) { $cost[0] = commafied($cost[0]); }

  $rv = join(".", @cost);

  if ($negative) { $rv = "-" . $rv; }

  return $rv;
}

sub commafied($) {
  #*
  # to insert commas before every 3rd number (from the right)
  # positive or negative numbers
  #*
  my ($num) = @_; # the number to insert commas into!

  my $negative = 0;
  if ($num =~ /^-/) {
    $negative = 1;
    $num =~ s/^-//;
  }
  $num =~ s/^(0)*//; # strip LEADING zeros from given number!
  $num =~ s/0/-/g; # convert zeros to dashes because ... computers!

  if ($num) {
    my @digits = reverse split("", $num);
    $num = "";

    for (my $i = 0; $i < @digits; $i += 3) {
      $num .= $digits[$i];
      if ($digits[$i+1]) { $num .= $digits[$i+1]; }
      if ($digits[$i+2]) { $num .= $digits[$i+2]; }
      if ($i < (@digits - 3)) { $num .= ","; }
      if ($i >= @digits) { last; }
    }

    #$num =~ s/,$//;
    $num = join("", reverse split("", $num));
    $num =~ s/-/0/g;
  }

  if ($negative) { $num = "-" . $num; }

  return $num; # a number with commas added
  #usage: my $prettyNum = commafied(1234567890);
}

সাবরোটাইনকে আপনার নির্দিষ্টকরণের সাথে সামঞ্জস্য করতে, কেবল নিম্নলিখিতটি সংশোধন করুন: if ($digit3 >= 5) { $digit3 = 0; $digit2++; if ($digit2 > 9) { $digit2 = 0; $digit1++; if ($digit1 > 9) { $digit1 = 0; $cost[0]++; } } } তাই এটি if ($digit1 >= 5) { $digit1 = 0; $cost[0]++; }return commafied($cost[0]);
জেরেট লয়েড

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