sdk
sdk copied to clipboard
add a method to produce engineering notation from a double value (double.toStringAsEngineering)
It is supported:
void main() {
print(1e2); // 100.0
print(1e-2); // 0.01
}
not its not engineering notation is all values in 10 power always be the multiple of 3
@alihassan143 do you want engineering notation for formatting? e.g. toStringAsExponential variant that just uses multiples of 3 exponents?
no try this its not working
the to stringasExponential() did not give the right answer as expected you can try different values the 5.9e+10 wheren E+10 is not the multiple of three the multiple of three is e+9
@alihassan143 yes, toStringAsExponential does not produce an engineering notation. That's why I asked if you are requesting an alternative to toStringAsExponential that would produce an engineering notation, i.e. you are asking for Dart to add double.toStringAsEngineering which would return string representing the given double value in an engineering notation?
The title of the issue that you have created is extremely unclear - so I am just trying to figure out what exactly you are requesting.
yes i want double to to add double.toStringAsEngineering so i did not have to run function to create engineering notation form doubel
/cc @lrhn for an opinion
So, "engineering notation" is like exponential/scientific notation, except that the exponential must be a multiple of 3, so you can have up to three digits to the left of the decimal point.
The main reason we don't have any other functionality than what is already there, is that that's all JavaScript provides for us.
We can definitely do some text-manipulation on the result of d.toExponential() afterwards, but we don't have a way, in JavaScript, to go directly to the engineering notation. That will make it slow compared to toExponential.
(The VM might be able to twiddle the existing scientific notation generation code, after all, the digits are all the same, the only difference is the exponent and the position of the decimal point. Which is also why string manipulation can work.)
I'd probably just write one myself. Maybe:
extension EngineeringNotation on double {
String toStringAsEngineering() {
var expString = this.toStringAsExponential();
var eIndex = expString.lastIndexOf("e");
if (eIndex < 0) return expString; // Not exponential.
var expIndex = eIndex + 1;
if (expString.startsWith("+", expIndex)) expIndex += 1;
var exponent = int.parse(expString.substring(expIndex));
var shift = exponent % 3; // 0, 1 or 2.
if (shift == 0) return expString; // Already multiple of 3
exponent -= shift;
var dotIndex = expString.indexOf(".");
int integerEnd;
int fractionalStart;
if (dotIndex < 0) {
integerEnd = eIndex;
fractionalStart = eIndex;
} else {
integerEnd = dotIndex;
fractionalStart = dotIndex + 1;
}
var preDotValue = expString.codeUnitAt(integerEnd - 1) ^ 0x30;
while (shift > 0) {
shift--;
preDotValue *= 10;
if (fractionalStart < eIndex) {
preDotValue += expString.codeUnitAt(fractionalStart++) ^ 0x30;
}
}
return "${integerEnd > 1 ? '-' : ''}$preDotValue."
"${expString.substring(fractionalStart, eIndex)}e${exponent >= 0 ? '+' : ''}$exponent";
}
}
(I can definitely optimize the heck out of that if necessary, but is it necessary?)
yes please do it i also write the same function for that to show double in engineering notation but other languages provide default feature of that
String floatToEngineering(double x) { int exp = 0, sign = 1; if (x < 0.0) { x = -x; sign = -sign; } while (x >= 1000.0) { x /= 1000.0; exp += 3; } while (x < 1.0) { x *= 1000.0; exp -= 3; } if (sign < 0) x = -x; return "${x.toStringAsFixed(4)}" + "e+" + "$exp"; }
that is my function which is quite fast
Doing multiplication and division by 1000 can lose precision on doubles, so to avoid that, you'd want to use the same, or similar, code that already does the toStringAsExponential. It's guaranteed to not lose precision and give a result string which is closer to the actual double value than to any other (so parsing pack using double.parse gives the same result back).
You'll only lose precision if your numbers have a large number of significant bits, and the distance to zero is large, so there will be multiple multiplications or divisions, so it'll work for a large number of actual values. That's not the bar for platform libraries, though. They should work correctly for all values.
Still, I'm sure I can do something in JavaScript (maybe round-trip the string through an Uint8List so I can move the . by one or two positions), and likely modify the native toStringAsExponential to choose an exponent which is a power of 3.
The question is whether it's worth adding to the platform libraries (we've made it so far without), and whether it really belongs in a general number formatting library like package:intl.
intl did not support engineering notation please add best funtions in dart please it save my lot of time
intl did not support engineering notation please add best funtions in dart please it save my lot of time
Try NumberFormat('###.##E+00').
The three # before the . causes the exponent to be a multiple of 3.
As you can see from the following, Intl can perhaps achieve what you require. There is not one 'engineering' format, but many:
import 'package:intl/intl.dart';
import 'dart:math' as math;
void main() {
demo('###.##E+00');
demo('##0.0#E0');
}
void demo(String pattern) {
final nf = NumberFormat(pattern);
print("--- '$pattern' ---");
final values = [
0,
for (final e in [-9, -8, -7, -1, 0, 1, 2, 3, 4, 5, 6])
1.23456 * math.pow(10, e)
];
for (final value in values) {
print(nf.format(value));
}
}
Result:
--- '###.##E+00' ---
0E+00
1.23E-09
12.35E-09
123.46E-09
123.46E-03
1.23E+00
12.35E+00
123.46E+00
1.23E+03
12.35E+03
123.46E+03
1.23E+06
--- '##0.0#E0' ---
0.0E0
1.23E-9
12.35E-9
123.46E-9
123.46E-3
1.23E0
12.35E0
123.46E0
1.23E3
12.35E3
123.46E3
1.23E6
@mosuem - some things could be better for users trying to get an engineering format. (1) a default engineering format would help many users get started (2) there is no discussion in the documentation that the exponent is controlled like this from the format - perhaps there should be an example of a custom engineering-like format (3) even the helper constructors have indirect and hard to understand descriptions - the documentation talks about things like "the locale's XXX_PATTERN' etc without an example of what this might mean.
Sorry if this is off-topic, but does anyone have any suggestions for the reverse? That is, for parsing a string in scientific notation to a double? I'm using string manipulation, but I had hoped that there were a core or otherwise popular package for a accomplishing the task.
@sneurlax Parsing a fixed format number can be achieved using https://pub.dev/documentation/convert/latest/convert/FixedDateTimeFormatter-class.html. For locale-dependent strings, we discourage parsing, as it is very brittle.
@sneurlax I would suggest simply using double.parse or double.tryParse. This will handle most of the examples from this thread, and will parse, say, 12e+08 and +1.2E9 as the same number.
If you need to reject one of these as not in the right format, then, as @mosuem says, the more brittle Intl parsing can be used.
If you mean something else by 'scientific notation' — something that has elements of layout such as 1.2×109 — then I don't believe that Intl can generate or parse numbers with different kinds of digits (normal digits vs superscripts).