如何解决小数到低俗分数,Kotlin Android NumberExt.kt 测试说明
我一直在尝试将Swift方法转换为Kotlin,但在这里没有得到任何帮助: Decimal to vulgar fraction conversion method- need help converting from Swift to Kotlin
我想我可以稍微改变一下我的问题,看看能否获得帮助。我需要逆向工程/代码解释方面的帮助,以便我自己进行转换。无论如何,我会通过这种方式了解更多。
如果有兴趣,可以在上方链接完整的代码/故事。 我快要聘请自由职业者来解决这个问题了。请帮忙 :) 此外,您可能需要知道此方法四舍五入到具有分数英寸的上,下标输出的数组。 需要解释以下几行:
val whole = number.toInt() // Of course i kNow what this does :)
val sign = if (whole < 0) -1 else 1 // I converted this myself and believe this is correct Kotlin
val fraction = number - whole.todouble() // And I kNow what this does
// need explanation from here down
for (i in 1..fractions.count()) {
if (abs(fraction) > (fractions[i].1 + fractions[i - 1].1) / 2) {
if ((fractions[i - 1].1) == (1.0)) run {
return@run Pair("${whole + sign}",(whole + sign).todouble())
} else {
return ("$whole" $fractions[i - 1].0,${whole.todouble() + (sign.todouble() * fractions[i - 1].1))
}
}
}
解决方法
通常,我倾向于在kotlin中编写诸如扩展功能/属性之类的计算功能,因为这样可以提高可用性。
NumberExt.kt
package ***
import kotlin.math.abs
/**
* @author aminography
*/
val Double.vulgarFraction: Pair<String,Double>
get() {
val whole = toInt()
val sign = if (whole < 0) -1 else 1
val fraction = this - whole
for (i in 1 until fractions.size) {
if (abs(fraction) > (fractionValues[i] + fractionValues[i - 1]) / 2) {
return if (fractionValues[i - 1] == 1.0) {
"${whole + sign}" to (whole + sign).toDouble()
} else {
"$whole ${fractions[i - 1]}" to whole + sign * fractionValues[i - 1]
}
}
}
return "$whole" to whole.toDouble()
}
val Float.vulgarFraction: Pair<String,Double>
get() = toDouble().vulgarFraction
private val fractions = arrayOf(
"",// 16/16
"\u00B9\u2075/\u2081\u2086",// 15/16
"\u215E",// 7/8
"\u00B9\u00B3/\u2081\u2086",// 13/16
"\u00BE",// 3/4
"\u00B9\u00B9/\u2081\u2086",// 11/16
"\u215D",// 5/8
"\u2079/\u2081\u2086",// 9/16
"\u00BD",// 1/2
"\u2077/\u2081\u2086",// 7/16
"\u215C",// 3/8
"\u2075/\u2081\u2086",// 5/16
"\u00BC",// 1/4
"\u00B3/\u2081\u2086",// 3/16
"\u215B",// 1/8
"\u00B9/\u2081\u2086",// 1/16
"" // 0/16
)
private val fractionValues = arrayOf(
1.0,15.0 / 16,7.0 / 8,13.0 / 16,3.0 / 4,11.0 / 16,5.0 / 8,9.0 / 16,1.0 / 2,7.0 / 16,3.0 / 8,5.0 / 16,1.0 / 4,3.0 / 16,1.0 / 8,1.0 / 16,0.0
)
测试
val rand = java.util.Random()
repeat(10) {
val sign = if (rand.nextBoolean()) 1 else -1
val number = rand.nextDouble() * rand.nextInt(100) * sign
val vulgar = number.vulgarFraction
println("Number: $number,Vulgar: ${vulgar.first},Rounded: ${vulgar.second}")
}
输出:
数字:17.88674468660217,粗俗:17⅞,四舍五入:17.875
数:-56.98489542592821,庸俗的:-57,四舍五入的-57.0
Number:39.275953137210614,Vulgar:39¼,四舍五入:39.25
数量:13.422939071442359,粗俗:13⁷/₁₆,舍入:13.4375
编号:-56.70735924226373,粗俗:-56¹¹/₁₆,四舍五入:-56.6875
编号:22.657555818202972,粗俗:22¹¹/₁₆,四舍五入:22.6875
编号:2.951680466645306,粗俗:2¹⁵/₁₆,四舍五入:2.9375
编号:-8.8311628631306,粗俗:-8¹³/₁₆,四舍五入:-8.8125
Number:28.639946409572655,Vulgar:28⅝,Rounded:28.625
数字:-28.439447873884085,粗俗:-28⁷/₁₆,舍入:-28.4375
说明
对整体逻辑的解释有些困难,我将尝试使其更加清晰。请注意,在以下代码段中,为了简化起见,我将fractionValues[i - 1]
替换为fractionValue
。
// First look at the 'fractions' array. It starts from 16/16=1 down to 0/16=0.
// So it covers all the possible 16 cases for dividing a number by 16.
// Note that 16/16=1 and 0/16=0 are the same in terms of division residual.
for (i in 1 until fractions.size) {
// Here,we are searching for the proper fraction that is the nearest one to the
// actual division residual.
// So,'|fraction| > (fractionValues[i] + fractionValues[i - 1]) / 2' means
// that the fraction is closer to the greater one in the 'fractionValues' array
// (i.e. 'fractionValues[i - 1]').
// Consider that we always want to find the proper 'fractionValues[i - 1]' and not
// 'fractionValues[i]' (According to the index of the 'for' loop which starts
// from 1,and not 0).
if (abs(fraction) > (fractionValues[i] + fractionValues[i - 1]) / 2) {
val fractionValue = fractionValues[i - 1]
// Here we've found the proper fraction value (i.e. 'fractionValue').
return if (fractionValue == 1.0) {
// 'fractionValue == 1.0' means that the actual division residual was greater
// than 15/16 but closer to 16/16=1. So the final value should be rounded to
// the nearest integer. Consider that in this case,the nearest integer for a
// positive number is one more and for a negative number,one less. Finally,// the summation with 'sign' does it for us :)
"${whole + sign}" to (whole + sign).toDouble()
} else {
// Here we have 'fractionValue < 1.0'. The only thing is to calculate the
// rounded value which is the sum of 'whole' and the discovered 'fractionValue'.
// As the value could be negative,by multiplying the 'sign' to the
// 'fractionValue',we will be sure that the summation is always correct.
"$whole $fractionValue" to whole + sign * fractionValue
}
}
}
// Finally,if we are not able to find a proper 'fractionValue' for the input number,// it means the number had an integer value.
return "$whole" to whole.toDouble()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。