Rounding error down when not adding a round number using RoundingMode HALF_UP in Kotlin - kotlin

consider below method:
fun main() {
var costs = 0
var transactionFee = 1.325
var total = (costs + transactionFee).toRoundedUpDouble()
}
fun Double.toRoundedUpDouble(fraction: Int = 2) =
BigDecimal(this).setScale(fraction, RoundingMode.HALF_UP).toDouble()
I want a number with 2 decimal after the comma, rounded up from 5. e.g. 1.325 becomes 1.33. This works when I add a round number, but not when I don't:
Output:
5.00 + 1.325 becomes 6.33 = good
5 + 1.325 becomes 6.33 = good
1 + 1.325 becomes 2.33 = good
1.325 becomes 1.32 = NOT GOOD
0 + 1.325 becomes 1.32 = NOT GOOD
0.00 + 1.325 becomes 1.32 = NOT GOOD
0.000 + 1.325 becomes 1.32 = NOT GOOD
This thread doesn't answer my question.

You say that this thread doesn't answer your question, but I it really does.
As mentioned in that thread, double literals lie to you, and println as well.
To know the actual value that these literals give you, you can use BigDecimal this way:
println(BigDecimal(1.325)) // 1.3249999999999999555910790149937383830547332763671875
println(BigDecimal(0 + 1.325)) // 1.3249999999999999555910790149937383830547332763671875
println(BigDecimal(5 + 1.325)) // 6.32500000000000017763568394002504646778106689453125
If you want accurate results, use BigDecimal from the start, and make sure to initialize them with strings, not double literals:
fun main() {
var costs = BigDecimal.ZERO
var transactionFee = BigDecimal("1.325")
var total = (costs + transactionFee).roundedUp()
println(total) // 1.33
println(total.toDouble()) // 1.33
}
fun BigDecimal.roundedUp(fraction: Int = 2) = setScale(fraction, RoundingMode.HALF_UP)

Related

Kotlin: Phone Bill calculator

I'm new at kotlin. Now I'm trying to code a Phone Bill Calculator, when I have to charge user 0.25 for every minute they were over their plan, and 15% tax on subtotal. I can't find the 15% tax.
import java.util.*
fun main(args: Array<String>) {
var numberOfCalls: Int
val phoneBill: Float
val thetax: Float = 15f
val scan = Scanner(System.`in`)
print("Enter the Total Minutes of Calls Made this Month: ")
numberOfCalls = scan.nextInt()
if (numberOfCalls <= 60) phoneBill = 10f else {
numberOfCalls = numberOfCalls - 60
phoneBill = ((10 + (numberOfCalls * 0.25 )).toFloat() + (thetax/100))
}
println("\nTelephone Bill this Month = $phoneBill")
}
Instead of using this formula bill = total + total * tax you was using this bill = total + taxPercentage which is wrong, you can calculate it like that and have theTaxAmount separately ( you can use it somewhere ):
fun main(args: Array<String>) {
var numberOfCalls: Int
val phoneBill: Float
val theTaxPercentage: Float = 0.15f
val scan = Scanner(System.`in`)
print("Enter the Total Minutes of Calls Made this Month: ")
numberOfCalls = scan.nextInt()
if (numberOfCalls <= 60) phoneBill = 10f else {
numberOfCalls -= 60
val phoneBillWithoutTax = (10 + (numberOfCalls * 0.25 )).toFloat()
val theTaxAmount = phoneBillWithoutTax * theTaxPercentage
phoneBill = phoneBillWithoutTax + theTaxAmount
}
println("\nTelephone Bill this Month = $phoneBill")
}
Your algebra error is that you didn't multiply the tax by anything. You just added it like it was a flat rate of 15 cents. A tax by percentage is multiplied by the total amount. And an algebra tip: it's less math (and less code) to multiply something by 115% (1.15) than it is to figure out what 15% would be and add it to the original value.
I find it is easier (and has clearer code) to solve a problem by doing minimal number of steps at a time instead of setting up all your variables at the start and then modifying them. Create/initialize what you need only immediately before you will use it. Basically, if you can write your logic out of vals and no vars, usually this will be a cleaner solution.
fun main(args: Array<String>) {
print("Enter the Total Minutes of Calls Made this Month: ")
val scan = Scanner(System.`in`)
val numberOfMinutes = scan.nextInt()
var excessMinutes = numberOfMinutes - 60
if (excessMinutes < 0) {
excessMinutes = 0
}
val bill = 10 + excessMinutes * 0.25
val taxedBill = bill * 1.15
println("\nTelephone Bill this Month = $taxedBill")
}
The four lines of code for excessMinutes can be shortened as below, but I wrote it out verbosely since you are just learning how the basic logic works, and if you're doing this for a class, the teacher might not expect you to be using helper functions like that yet.
val excessMinutes = max(0, numberOfMinutes - 60)

For loop must have an iterator()

I need this service in which if the person stays for longer than 30 minutes, they have to pay an extra $10 every 15 minutes (and for the fraction of the 15 as well).
I designed it like this so far:
var checkInTime: Calendar
val totalTime: Long
get() = (Calendar.getInstance().timeInMillis - checkInTime.timeInMillis) / MIN_IN_MILISEC
fun getTime(totalTime:Long): Int{
var finalPrice = 0
var initialPrice = 20
if(totalTime<31){
finalFee = initialPrice
} else {
val extraPrice = 10
val extraTime = 15
finalFee = initialPrice
for(extraTime in totalTime){
finalFee += extraTime
}
return finalFee
}
I get the error "For loop must have an iterator()" when I try to loop through the totalTime when it's more than 30 minutes so that I can add $10 every 15 extra minutes. I need some help as to how to add to the finalFee every extra 15 minutes the person stays since my method is not working.
Thank you.
Let's take a look at your getTime function:
You're using a Long as totalTime. You can measure it in minutes to simplify your calculation (since all time values are measured in minutes). Since a Long type in Kotlin stores a integer up to 9,223,372,036,854,775,807 and no soul on Earth will use your service for that long (this represents 17 billion milleniums), you can just use an Int.
You're not declaring the finalFee variable, thus the code will raise an
"Unresolved reference" error. Since you're not using the finalPrice variable, I'm assuming you wanted to use this instead.
You're trying to iterate over a numeric value (in this case, totalTime, which is a Long). You can iterate over each element of a List, but how would you iterate over each element of an integer? I'm assuming you want to do a certain action totalTime number of times. In this case, you would use ranges.
You're also not using the variables extraPrice and extraTime.
There's code that's common to both if-else conditions (finalPrice = initialPrice), so you can extract that to outside the if-statement.
Refactoring your function:
fun getTime(totalTime: Int): Int {
var finalPrice = 20
if (totalTime >= 30) {
(0 until totalTime).forEach {
finalPrice += 15
}
}
return finalPrice
}
It's shorter, but still doesn't do what it's supposed to: let's suppose totalTime is equal to 45. The person got 30 minutes costing $20 and only have to pay $10 for every 15 minutes, therefore will only pay $30 total. Your function is considering that the person will have to pay $15 for every minute they stayed, because it uses a for-loop that goes from 0 to totalTime. For that, you need a for-loop that goes from 30 (the time limit) from the total time (the totalTime) every 15 minutes:
fun getTime(totalTime: Int): Int {
var finalPrice = 20
if (totalTime > 30) {
(30 until totalTime step 15).forEach {
finalPrice += 10
}
}
return finalPrice
}
Better yet, you don't even need a for-loop, you can just use maths:
fun getTime(totalTime: Int): Int {
var finalPrice = 20
if (totalTime > 30) {
finalPrice += ((totalTime - 30) / 15) * 10
// ^^^^^^^^^^^^^^^^ Get the exceeding time
// ^^^^^^^^^^^^^^^^^^^^^^^ How many 15 minutes are there?
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Put $10 for every 15 minutes
}
return finalPrice
}
The last part: your question said you need to consider the fraction of 15 as well. Therefore, you need to use a real value, not an integer. Let's change it to a Double:
fun getTime(totalTime: Int): Double {
var finalPrice = 20.0
if (totalTime > 30) {
finalPrice += ((totalTime - 30) / 15.0) * 10
}
return finalPrice
}
Let's test your function:
fun main() {
println(getTime(0)) // Outputs 20.0
println(getTime(10)) // Outputs 20.0
println(getTime(30)) // Outputs 20.0
println(getTime(45)) // Outputs 30.0
println(getTime(60)) // Outputs 40.0
println(getTime(70)) // Outputs 46.666...
}

Kotlin/Java formatting Double values

My current formatting is this
DecimalFormat("#,##0.00").format(value)
I need to handle values like this
0.00 //ok
0.45 //ok
0.002 //Need to show 0.002 or 0.0020
0.0003 //Need to show 0.0003 or 0.00030
0.00004 //Need to show 0.00004 or 0.000040
0.00234567 //Need to show 0.0023
But sure the above code will not work on fractional part where a non zero value started at thousandth place else I will just ended up displaying 0.00 as if it is totally a zero value. I still want the above formatting with comma when dealing with whole number but also allowing me to format when non zero starts beyond hundredths place.
Further sample
0.0492 // 0.04 or 0.05 much better
700.356 // 700.35 or 700.36 much better
54232.542234 // 54,232.54
Try multiplying the number by 10 until you know you got to two non zero digits. This way you will get the number of decimal points you have to round up.
After that you use the NumberFormat to format the number like this:
val format = NumberFormat.getInstance()
format.maximumFractionDigits = nrOfDecimalPoints
val formattedNumber = format.format(yourNumber)
This way you will keep the thousands separator "," and the decimal will be cut off after two non zero digits.
EDIT
This is how the custom function looks like:
private fun customFormat(number: Double): String{
var temp = number - number.toInt()
temp *= 100
var nrDec = 2
if (number <= 0.0){
return "0.00"
}
if (temp >= 1.0){
val format = NumberFormat.getInstance(Locale.US)
format.maximumFractionDigits = nrDec
return format.format(number)
}
while (temp < 1.0 && nrDec < 15){
temp *= 10
nrDec ++
}
if((temp * 10 % 10) != 0.0){
nrDec++
}
val format = NumberFormat.getInstance(Locale.US)
format.maximumFractionDigits = nrDec
return format.format(number)
}
You can do it like this in order to cut of tailing 0:
public static void main(String []args){
double number1 = 0.2;
double number2 = 1.55;
double number3 = 0.00005;
double number4 = 0.50000;
DecimalFormat df = new DecimalFormat("###,##0.00#########");
System.out.println(df.format(number1)); // 0.20
System.out.println(df.format(number2)); // 1.55
System.out.println(df.format(number3)); // 0.00005
System.out.println(df.format(number4)); // 0.50
}
You just need to know how far your decimal digits should be checked.

Write a program that reads a three-digit number(923), reverses the order of its digits, and outputs a new number(329) in Kotlin?

import java.util.Scanner
fun main() {
val scanner = Scanner(System.in)
}
I know there is possibility of using String.reversed() but the exercise is part of Integers in action so I need to solve it only with integers.
thats pretty easy,
var num = 923
var reversed = 0
while (num != 0) {
val digit = num % 10
reversed = reversed * 10 + digit
num /= 10
}
println("Reversed Number: $reversed")

Convert numbers in Chinese characters to arabic numbers

I am a newbie in programming and i start with Objective C as my first language.
I am messing around with some books and tutorials, at last programing a calculator...
Everything fine and i am getting into (programming makes really fun)
Now i am asking myself how I could translate arabic numbers to chinese numbers
(e.g. arabic 4 is in chinese 四 and 8 is 八 which means 四 + 四 = 八
The chinese number system is kind of different than arabic they have signs for 100, 1000, 10000 and ja kind of twisted, which screws up my brain ... anyway do anybody have some advice, hints, tips or solutions how i can tell the computer how to work with this numbers, or even how to calculate with them?
I think everything is possible so i wont ask "If its even possible?"
Considering the Chinese numerical system (Mandarin) as described by wikipedia http://en.wikipedia.org/wiki/Chinese_numerals, where for instance:
45 is interpreted as [4] [10] [5] and written 四十五
114 is interpreted as [1] [100] [1] [10] [4] and written 一百一十四
So the trick is to decompose a number as powers of 10:
x = c(k)*10^k + ... + c(1)*10 + c(0)
where k is the largest power of 10 that divides x such that the quotient is at least 1. In the 2nd example above, 114 = 1*10^2 + 1*10 + 4.
This x = c(k)*10^k + ... + c(1)*10 + c(0) becomes [c(k)][10^k]...[c(1)][10][c(0)]. In the 2nd example again, 114 = [1] [100] [1] [10] [4].
Then map each number within bracket to the corresponding sinogram:
0 = 〇
1 = 一
2 = 二
3 = 三
4 = 四
5 = 五
6 = 六
7 = 七
8 = 八
9 = 九
10 = 十
100 = 百
1000 = 千
10000 = 万
As long as you keep track of the [c(k)][10^k]...[c(1)][10][c(0)] form, it's easy to convert to an integer that the computer can handle or to the corresponding Chinese numeral. So it's this [c(k)][10^k]...[c(1)][10][c(0)] form that I'd store in an integer array of size k+2.
I'm not familiar with Objective-C, thus I can't help you with a solution for iOS.
Nonetheless, following is the Java code for Android...
I assumed it might help you, as well as it helped me.
double text2double(String text) {
String[] units = new String[] { "〇", "一", "二", "三", "四",
"五", "六", "七", "八", "九"};
String[] scales = new String[] { "十", "百", "千", "万",
"亿" };
HashMap<String, ScaleIncrementPair> numWord = new HashMap<String, ScaleIncrementPair>();
for (int i = 0; i < units.length; i++) {
numWord.put(units[i], new ScaleIncrementPair(1, i));
}
numWord.put("零", new ScaleIncrementPair(1, 0));
numWord.put("两", new ScaleIncrementPair(1, 2));
for (int i = 0; i < scales.length; i++) {
numWord.put(scales[i], new ScaleIncrementPair(Math.pow(10, (i + 1)), 0));
}
double current = 0;
double result = 0;
for (char character : text.toCharArray()) {
ScaleIncrementPair scaleIncrement = numWord.get(String.valueOf(character));
current = current * scaleIncrement.scale + scaleIncrement.increment;
if (scaleIncrement.scale > 10) {
result += current;
current = 0;
}
}
return result + current;
}
class ScaleIncrementPair {
public double scale;
public int increment;
public ScaleIncrementPair(double s, int i) {
scale = s;
increment = i;
}
}
You can make use of NSNumberFormatter.
Like below code, firstly get NSNumber from chinese characters, then combine them.
func getNumber(fromText text: String) -> NSNumber? {
let locale = Locale(identifier: "zh_Hans_CN")
let numberFormatter = NumberFormatter()
numberFormatter.locale = locale
numberFormatter.numberStyle = .spellOut
guard let number = numberFormatter.number(from: text) else { return nil }
print(number)
return number
}