এমন কোনও ফাংশন রয়েছে যা একটি ডাবল কেটে বা গোল করতে পারে? আমার কোডের এক পর্যায়ে আমি একটি নম্বর চাই: 1.23456789
গোল করতে হবে to1.23
এমন কোনও ফাংশন রয়েছে যা একটি ডাবল কেটে বা গোল করতে পারে? আমার কোডের এক পর্যায়ে আমি একটি নম্বর চাই: 1.23456789
গোল করতে হবে to1.23
উত্তর:
আপনি ব্যবহার করতে পারেন scala.math.BigDecimal
:
BigDecimal(1.23456789).setScale(2, BigDecimal.RoundingMode.HALF_UP).toDouble
অন্যান্য কয়েকটি গোলাকার মোড রয়েছে , যা দুর্ভাগ্যক্রমে বর্তমানে খুব ভালভাবে নথিভুক্ত করা হয়নি (যদিও তাদের জাভা সমতুল্য )।
"%.2f".format(x).toDouble
এই ক্ষেত্রে সুপারিশ করব । কেবল 2x ধীর গতির এবং আপনাকে কেবল এমন একটি লাইব্রেরি ব্যবহার করতে হবে যা আপনি ইতিমধ্যে জানেন।
scala> "%.2f".format(0.714999999999).toDouble
res13: Double = 0.71
কিন্তু scala> "%.2f".format(0.715).toDouble
res14: Double = 0.72
।
এখানে বিগডিসিমালগুলি ছাড়া আর একটি সমাধান solution
truncate:
(math floor 1.23456789 * 100) / 100
রাউন্ড:
(math rint 1.23456789 * 100) / 100
অথবা যে কোনও ডাবল এন এবং নির্ভুলতার জন্য পি:
def truncateAt(n: Double, p: Int): Double = { val s = math pow (10, p); (math floor n * s) / s }
বৃত্তাকার ক্রিয়াকলাপের জন্য, তড়িঘড়ি ব্যবহার করে এবার অনুরূপ করা যেতে পারে:
def roundAt(p: Int)(n: Double): Double = { val s = math pow (10, p); (math round n * s) / s }
যা আরও পুনরায় ব্যবহারযোগ্য, উদাহরণস্বরূপ যখন অর্থের পরিমাণের পরিমাণগুলি নিম্নলিখিত ব্যবহার করা যায়:
def roundAt2(n: Double) = roundAt(2)(n)
NaN
, তাই না?
floor
অর্থাৎ truncateAt(1.23456789, 8)
ফিরে আসবে 1.23456788
যখন roundAt(1.23456789, 8)
সঠিক মান ফিরে আসবে1.23456789
যেহেতু কেউ %
এখনও অপারেটরটির কথা উল্লেখ করেনি, এখানে আসে। এটি কেবল ছাঁটাই করে এবং আপনি ফ্লোটিং পয়েন্টের ভুল ব্যবহার না করে ফেরতের মূল্যের উপর নির্ভর করতে পারবেন না, তবে কখনও কখনও এটি কার্যকরও হয়:
scala> 1.23456789 - (1.23456789 % 0.01)
res4: Double = 1.23
26.257391515826225 - 0.057391515826223094 = 26.200000000000003
কেমন :
val value = 1.4142135623730951
//3 decimal places
println((value * 1000).round / 1000.toDouble)
//4 decimal places
println((value * 10000).round / 10000.toDouble)
((1.949 * 1000).toInt - ((1.949 * 1000).toInt % 10)) / 1000.toDouble
এটি খুব বেশি পরীক্ষা করা হয়নি। এই কোডটি 2 দশমিক জায়গায় করবে।
সম্পাদনা: @ryryguy নির্দেশিত সমস্যাটি ঠিক করেছে। (ধন্যবাদ!)
যদি আপনি এটি দ্রুত হতে চান, কাইটো সঠিক ধারণা আছে। math.pow
ধীর, যদিও। যে কোনও মানক ব্যবহারের জন্য আপনি একটি পুনরাবৃত্ত ফাংশন দিয়ে ভাল off
def trunc(x: Double, n: Int) = {
def p10(n: Int, pow: Long = 10): Long = if (n==0) pow else p10(n-1,pow*10)
if (n < 0) {
val m = p10(-n).toDouble
math.round(x/m) * m
}
else {
val m = p10(n).toDouble
math.round(x*m) / m
}
}
আপনি Long
(অর্থাত্ 18 ডিজিট) এর সীমার মধ্যে থাকলে এটি 10x দ্রুত হয় , তাই আপনি 10 and 18 এবং 10 ^ -18 এর মধ্যে যে কোনও জায়গায় যেতে পারেন।
scala> def r5(x:Double) = math.round(x*100000)*0.000001; r5(0.23515)
==> res12: Double = 0.023514999999999998
। পরিবর্তে তাৎপর্য দ্বারা ভাগ করুন:math.round(x*100000)/100000.0
p10
অ্যারে লুকোচুরির সাথে পুনরাবৃত্ত ফাংশনটি প্রতিস্থাপন করতেও কার্যকর হতে পারে : অ্যারে মেমরির খরচ প্রায় 200 বাইট বাড়িয়ে দেবে তবে সম্ভবত কল প্রতি একাধিক পুনরাবৃত্তি সংরক্ষণ করবে।
আপনি অন্তর্ভুক্ত ক্লাস ব্যবহার করতে পারেন:
import scala.math._
object ExtNumber extends App {
implicit class ExtendedDouble(n: Double) {
def rounded(x: Int) = {
val w = pow(10, x)
(n * w).toLong.toDouble / w
}
}
// usage
val a = 1.23456789
println(a.rounded(2))
}
যারা আগ্রহী তাদের জন্য, প্রস্তাবিত সমাধানগুলির জন্য এখানে কিছু সময় দেওয়া হয়েছে ...
Rounding
Java Formatter: Elapsed Time: 105
Scala Formatter: Elapsed Time: 167
BigDecimal Formatter: Elapsed Time: 27
Truncation
Scala custom Formatter: Elapsed Time: 3
ট্র্যাঙ্কেশন সবচেয়ে দ্রুত, তারপরে বিগডিসিমাল। মনে রাখবেন এই পরীক্ষাগুলি কোনও মানদণ্ডের সরঞ্জাম ব্যবহার না করে নরমাল স্ক্যাল কার্যকর করা হয়েছিল।
object TestFormatters {
val r = scala.util.Random
def textFormatter(x: Double) = new java.text.DecimalFormat("0.##").format(x)
def scalaFormatter(x: Double) = "$pi%1.2f".format(x)
def bigDecimalFormatter(x: Double) = BigDecimal(x).setScale(2, BigDecimal.RoundingMode.HALF_UP).toDouble
def scalaCustom(x: Double) = {
val roundBy = 2
val w = math.pow(10, roundBy)
(x * w).toLong.toDouble / w
}
def timed(f: => Unit) = {
val start = System.currentTimeMillis()
f
val end = System.currentTimeMillis()
println("Elapsed Time: " + (end - start))
}
def main(args: Array[String]): Unit = {
print("Java Formatter: ")
val iters = 10000
timed {
(0 until iters) foreach { _ =>
textFormatter(r.nextDouble())
}
}
print("Scala Formatter: ")
timed {
(0 until iters) foreach { _ =>
scalaFormatter(r.nextDouble())
}
}
print("BigDecimal Formatter: ")
timed {
(0 until iters) foreach { _ =>
bigDecimalFormatter(r.nextDouble())
}
}
print("Scala custom Formatter (truncation): ")
timed {
(0 until iters) foreach { _ =>
scalaCustom(r.nextDouble())
}
}
}
}
...truncate or round a Double
।
doubleParts.tail
এবং স্ট্রিং সহ কনক্যাট করুন "" এবং doubleParts. head
এবং দ্বিগুণ করতে পার্স।
toString.split(".")
এবং doubleParts.head/tail
পরামর্শ অতিরিক্ত অ্যারে বরাদ্দ প্লাস স্ট্রিং কনকন্টেশন দ্বারা ভুগতে পারে। যদিও নিশ্চিত হওয়ার জন্য পরীক্ষা করা দরকার।
সম্প্রতি, আমি একই সমস্যার মুখোমুখি হয়েছি এবং নিম্নলিখিত পদ্ধতির সাহায্যে এটি সমাধান করেছি
def round(value: Either[Double, Float], places: Int) = {
if (places < 0) 0
else {
val factor = Math.pow(10, places)
value match {
case Left(d) => (Math.round(d * factor) / factor)
case Right(f) => (Math.round(f * factor) / factor)
}
}
}
def round(value: Double): Double = round(Left(value), 0)
def round(value: Double, places: Int): Double = round(Left(value), places)
def round(value: Float): Double = round(Right(value), 0)
def round(value: Float, places: Int): Double = round(Right(value), places)
আমি এই এসও ইস্যুটি ব্যবহার করেছি । আমার কাছে ফ্লোট \ ডাবল এবং ইনপিলিটেড \ সুস্পষ্ট বিকল্প উভয়ের জন্য বেশ কয়েকটি ওভারলোডেড ফাংশন রয়েছে। দ্রষ্টব্য, অতিরিক্ত লোড ফাংশনগুলির ক্ষেত্রে আপনাকে স্পষ্টভাবে রিটার্নের ধরণের উল্লেখ করতে হবে।
স্কেলা f
ইন্টারপোলটার ব্যবহার করে এটি পরিচালনা করা খুব সহজ - https://docs.scala-lang.org/overviews/core/string-interpolation.html
মনে করুন আমরা 2 দশমিক স্থানে গোল করতে চাই:
scala> val sum = 1 + 1/4D + 1/7D + 1/10D + 1/13D
sum: Double = 1.5697802197802198
scala> println(f"$sum%1.2f")
1.57
আপনি যদি পারফরম্যান্সের বিষয়ে চিন্তা করেন তবে আমি বিগডিসিমাল ব্যবহার করব না। বিগডিসিমাল সংখ্যাগুলিকে স্ট্রিংয়ে রূপান্তর করে এবং তারপরে আবার পার্স করে:
/** Constructs a `BigDecimal` using the decimal text representation of `Double` value `d`, rounding if necessary. */
def decimal(d: Double, mc: MathContext): BigDecimal = new BigDecimal(new BigDec(java.lang.Double.toString(d), mc), mc)
কৈতোর পরামর্শ অনুসারে আমি গণিতের হেরফেরগুলিতে আটকে যাচ্ছি ।
আপনি এটি করতে পারেন: Math.round(<double precision value> * 100.0) / 100.0
তবে ম্যাথ.গ্রাউন্ডটি দ্রুততম তবে এটি কোণার ক্ষেত্রে খুব বেশি সংখ্যক দশমিক স্থানের (যেমন গোলাকার (1000.0 ডি, 17)) বা বৃহত পূর্ণসংখ্যার অংশ (যেমন গোলাকার (90080070060.1 ডি, 9) এর সাথে খারাপভাবে ভেঙে যায় )।
বিগডিসিমাল ব্যবহার করুন এটি কিছুটা অক্ষম হওয়ায় এটি মানগুলিকে স্ট্রিংয়ে রূপান্তর করে তবে আরও স্বস্তি:
BigDecimal(<value>).setScale(<places>, RoundingMode.HALF_UP).doubleValue()
রাউন্ডিং মোডের আপনার পছন্দ ব্যবহার করুন।
যদি আপনি কৌতূহলী হন এবং আরও কেন জানতে চান তবে কেন এটি হয় আপনি এটি পড়তে পারেন: