S'il est divisible, veuillez calculer jusqu'au point où il est divisible. Mais s'il n'est pas divisible, trouvez toujours le quotient avec le même nombre de chiffres valides. Je pense qu'il sera nécessaire pour une application qui affiche le résultat du calcul de la division comme une calculatrice. Je n'ai pas pu trouver un bon moyen sur le net, alors j'y ai pensé moi-même (`・ ω ・ ´)
(Ajouté le 16/07/2018) J'ai ajouté un exemple d'utilisation au format GIF ci-dessous pour indiquer clairement ce que vous souhaitez atteindre. En passant, cette image a été prise avec une application de calcul appelée Calc Leaf que j'ai développée.
De cette manière, même si la réponse est un nombre infini, le but est de l'afficher correctement dans la plage affichable.
Voici quelques exemples de sortie.
Je vais l'omettre ici, mais si vous formatez la réponse obtenue avec Decimal Format
, l'affichage sera beau.
Division.java
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Division {
public static final int SIGNIFICANT_DIGITS = 3; //Nombre de chiffres valides
public static void main(String[] args) {
try {
System.out.println(divided("10000", "3")); // 3330
System.out.println(divided("1000", "3")); // 333
System.out.println(divided("100", "3")); // 33.3
System.out.println(divided("10", "3")); // 3.33
System.out.println(divided("1", "3")); // 0.333
System.out.println(divided("1", "30")); // 0.0333
System.out.println(divided("1", "300")); // 0.00333
System.out.println(divided("1", "3000")); // 0.000333
System.out.println(divided("1", "30000")); // 0.0000333
} catch(NumberFormatException nfe) {
System.out.println("Error: Not a number.");
} catch(ArithmeticException ae) {
System.out.println("Error: Impossible to calculate.");
} catch(Exception e) {
System.out.println("Error: Unexpected.");
}
}
public static String divided(String dividend, String divisor) throws Exception {
BigDecimal bdDividend = new BigDecimal(dividend);
BigDecimal bdDivisor = new BigDecimal(divisor);
BigDecimal answer = null;
try {
//S'il est divisible, divisez-le tel quel
answer = bdDividend.divide(bdDivisor);
} catch(ArithmeticException arithmeticException) {
//S'il n'est pas divisible, calculez une échelle valide (dans cet exemple, l'arrondi est arrondi)
answer = bdDividend.divide(bdDivisor, getSignificantScale(bdDividend, bdDivisor), RoundingMode.HALF_UP);
}
return answer.stripTrailingZeros().toPlainString();
}
public static int getSignificantScale(BigDecimal dividend, BigDecimal divisor) {
//Valeur absolue à l'exclusion des zéros de fin après la virgule décimale
BigDecimal bd1 = dividend.abs().stripTrailingZeros();
BigDecimal bd2 = divisor.abs().stripTrailingZeros();
//Créer une chaîne de caractères simple selon un nombre naturel
int decimalDigits = bd1.scale() > bd2.scale() ? bd1.scale() : bd2.scale();
if (decimalDigits < 0) decimalDigits = 0;
String s1 = bd1.scaleByPowerOfTen(decimalDigits).toPlainString();
String s2 = bd2.scaleByPowerOfTen(decimalDigits).toPlainString();
//Calculer et renvoyer une échelle valide
return SIGNIFICANT_DIGITS - (s1.length() - s2.length()) - (s1.compareTo(s2) >= 0 ? 1 : 0);
}
}
Vous pouvez le copier et le coller dans Try kotlin tel quel.
Vous pouvez utiliser let
pour faire val
sur une ligne où vous voulez decimalDigits
, mais je l'ai arrêté parce que c'est subtil.
Division.kt
import java.math.BigDecimal
import java.math.RoundingMode
const val SIGNIFICANT_DIGITS: Int = 3 //Nombre de chiffres valides
fun main(args: Array<String>) {
try {
println(divided("10000", "3")) // 3330
println(divided("1000", "3")) // 333
println(divided("100", "3")) // 33.3
println(divided("10", "3")) // 3.33
println(divided("1", "3")) // 0.333
println(divided("1", "30")) // 0.0333
println(divided("1", "300")) // 0.00333
println(divided("1", "3000")) // 0.000333
println(divided("1", "30000")) // 0.0000333
} catch(nfe: NumberFormatException) {
println("Error: Not a number.")
} catch(ae: ArithmeticException) {
println("Error: Impossible to calculate.")
} catch(e: Exception) {
println("Error: Unexpected.")
}
}
fun divided(dividend: String, divisor: String): String {
val bdDividend = BigDecimal(dividend)
val bdDivisor = BigDecimal(divisor)
val answer = try {
//S'il est divisible, divisez-le tel quel
bdDividend.divide(bdDivisor)
} catch(ae: ArithmeticException) {
//S'il n'est pas divisible, calculez une échelle valide (dans cet exemple, l'arrondi est arrondi)
bdDividend.divide(bdDivisor, getSignificantScale(bdDividend, bdDivisor), RoundingMode.HALF_UP)
}
return answer.stripTrailingZeros().toPlainString()
}
fun getSignificantScale(dividend: BigDecimal, divisor: BigDecimal): Int {
//Valeur absolue à l'exclusion des zéros de fin après la virgule décimale
val bd1 = dividend.abs().stripTrailingZeros()
val bd2 = divisor.abs().stripTrailingZeros()
//Créer une chaîne de caractères simple selon un nombre naturel
var decimalDigits = if (bd1.scale() > bd2.scale()) bd1.scale() else bd2.scale()
if (decimalDigits < 0) decimalDigits = 0
val s1 = bd1.scaleByPowerOfTen(decimalDigits).toPlainString()
val s2 = bd2.scaleByPowerOfTen(decimalDigits).toPlainString()
//Calculer et renvoyer une échelle valide
return SIGNIFICANT_DIGITS - (s1.length - s2.length) - (if (s1 >= s2) 1 else 0)
}
Vous pouvez tester vous-même le code ci-dessus et l'utiliser comme vous le souhaitez. Le code de test que j'ai effectué a été téléchargé sur ~~ github (publié en réponse aux commentaires de kaizen_nagoya), Nous avons vérifié environ 50 modèles en fonction de la relation entre le nombre à diviser et le nombre à diviser, la position de la virgule décimale, positive / négative, et s'il s'agit ou non d'une notation exponentielle, et effacé les exigences. Cependant, il est indéniable qu'il manque d'objectivité car je le faisais seul (´ ・ ω ・ `) Donc, ceux qui révisent et revérifient sont les bienvenus! Aussi, si vous avez des informations sur des bibliothèques ou des sites de référence qui font la même chose, je serais très heureux si vous pouviez me le faire savoir! (J'y ai réfléchi maintenant, mais il est peut-être répertorié dans le dictionnaire mathématique. Je ne l'ai pas.)
getSignificantScale
est en fait utilisé dans mon application de calculatrice développée CalcLeaf, mais c'est en fait un peu Il y a une différence dans la mise en œuvre.
Le fait est que "0 est renvoyé si le résultat du calcul d'une échelle valide est négatif" comme indiqué ci-dessous.
Sample.java
int significantScale = SIGNIFICANT_DIGITS - (s1.length() - s2.length()) - (s1.compareTo(s2) >= 0 ? 1 : 0);
return significantScale < 0 ? 0 : significantScale;
Dans le cas d'une calculatrice, par exemple, si la réponse de 1 000 000 000 000 ÷ 3 devient 333 333 333 330, c'est désagréable, donc Calc Leaf l'a ajustée comme spécification.
J'aurais aimé pouvoir le faire en standard avec l'API Java. Je me demande si les gens en Java y réfléchiront s'ils le voient.
Recommended Posts