Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
/goPublic

Commit0a164d2

Browse files
committed
[release-branch.go1.3] fmt: fix signs when zero padding.
««« CL 103480043 / 777dd5a434dbfmt: fix signs when zero padding.Bug was introduced recently. Add more tests, fix the bugs.Suppress + sign when not required in zero padding.Do not zero pad infinities.All old tests still pass.This time for sure!Fixes#8217.LGTM=rscR=golang-codereviews, dan.kortschak, rscCC=golang-codereviewshttps://golang.org/cl/103480043»»»LGTM=r, rscR=r, rscCC=golang-codereviewshttps://golang.org/cl/110040043
1 parent9d7a83a commit0a164d2

File tree

2 files changed

+147
-39
lines changed

2 files changed

+147
-39
lines changed

‎src/pkg/fmt/fmt_test.go‎

Lines changed: 113 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -513,9 +513,76 @@ var fmtTests = []struct {
513513
{"%0.100f",1.0,zeroFill("1.",100,"")},
514514
{"%0.100f",-1.0,zeroFill("-1.",100,"")},
515515

516-
// Zero padding floats used to put the minus sign in the middle.
517-
{"%020f",-1.0,"-000000000001.000000"},
516+
// Comparison of padding rules with C printf.
517+
/*
518+
C program:
519+
#include <stdio.h>
520+
521+
char *format[] = {
522+
"[%.2f]",
523+
"[% .2f]",
524+
"[%+.2f]",
525+
"[%7.2f]",
526+
"[% 7.2f]",
527+
"[%+7.2f]",
528+
"[%07.2f]",
529+
"[% 07.2f]",
530+
"[%+07.2f]",
531+
};
532+
533+
int main(void) {
534+
int i;
535+
for(i = 0; i < 9; i++) {
536+
printf("%s: ", format[i]);
537+
printf(format[i], 1.0);
538+
printf(" ");
539+
printf(format[i], -1.0);
540+
printf("\n");
541+
}
542+
}
543+
544+
Output:
545+
[%.2f]: [1.00] [-1.00]
546+
[% .2f]: [ 1.00] [-1.00]
547+
[%+.2f]: [+1.00] [-1.00]
548+
[%7.2f]: [ 1.00] [ -1.00]
549+
[% 7.2f]: [ 1.00] [ -1.00]
550+
[%+7.2f]: [ +1.00] [ -1.00]
551+
[%07.2f]: [0001.00] [-001.00]
552+
[% 07.2f]: [ 001.00] [-001.00]
553+
[%+07.2f]: [+001.00] [-001.00]
554+
*/
555+
{"%.2f",1.0,"1.00"},
556+
{"%.2f",-1.0,"-1.00"},
557+
{"% .2f",1.0," 1.00"},
558+
{"% .2f",-1.0,"-1.00"},
559+
{"%+.2f",1.0,"+1.00"},
560+
{"%+.2f",-1.0,"-1.00"},
561+
{"%7.2f",1.0," 1.00"},
562+
{"%7.2f",-1.0," -1.00"},
563+
{"% 7.2f",1.0," 1.00"},
564+
{"% 7.2f",-1.0," -1.00"},
565+
{"%+7.2f",1.0," +1.00"},
566+
{"%+7.2f",-1.0," -1.00"},
567+
{"%07.2f",1.0,"0001.00"},
568+
{"%07.2f",-1.0,"-001.00"},
569+
{"% 07.2f",1.0," 001.00"},
570+
{"% 07.2f",-1.0,"-001.00"},
571+
{"%+07.2f",1.0,"+001.00"},
572+
{"%+07.2f",-1.0,"-001.00"},
573+
574+
// Complex numbers: exhaustively tested in TestComplexFormatting.
575+
{"%7.2f",1+2i,"( 1.00 +2.00i)"},
576+
{"%+07.2f",-1-2i,"(-001.00-002.00i)"},
577+
// Zero padding does not apply to infinities.
578+
{"%020f",math.Inf(-1)," -Inf"},
579+
{"%020f",math.Inf(+1)," +Inf"},
580+
{"% 020f",math.Inf(-1)," -Inf"},
581+
{"% 020f",math.Inf(+1)," Inf"},
582+
{"%+020f",math.Inf(-1)," -Inf"},
583+
{"%+020f",math.Inf(+1)," +Inf"},
518584
{"%20f",-1.0," -1.000000"},
585+
// Make sure we can handle very large widths.
519586
{"%0100f",-1.0,zeroFill("-",99,"1.000000")},
520587

521588
// Complex fmt used to leave the plus flag set for future entries in the array
@@ -601,6 +668,50 @@ func TestSprintf(t *testing.T) {
601668
}
602669
}
603670

671+
// TestComplexFormatting checks that a complex always formats to the same
672+
// thing as if done by hand with two singleton prints.
673+
funcTestComplexFormatting(t*testing.T) {
674+
varyesNo= []bool{true,false}
675+
varsigns= []float64{1,0,-1}
676+
for_,plus:=rangeyesNo {
677+
for_,zero:=rangeyesNo {
678+
for_,space:=rangeyesNo {
679+
for_,char:=range"fFeEgG" {
680+
realFmt:="%"
681+
ifzero {
682+
realFmt+="0"
683+
}
684+
ifspace {
685+
realFmt+=" "
686+
}
687+
ifplus {
688+
realFmt+="+"
689+
}
690+
realFmt+="10.2"
691+
realFmt+=string(char)
692+
// Imaginary part always has a sign, so force + and ignore space.
693+
imagFmt:="%"
694+
ifzero {
695+
imagFmt+="0"
696+
}
697+
imagFmt+="+"
698+
imagFmt+="10.2"
699+
imagFmt+=string(char)
700+
for_,realSign:=rangesigns {
701+
for_,imagSign:=rangesigns {
702+
one:=Sprintf(realFmt,complex(realSign,imagSign))
703+
two:=Sprintf("("+realFmt+imagFmt+"i)",realSign,imagSign)
704+
ifone!=two {
705+
t.Error(f,one,two)
706+
}
707+
}
708+
}
709+
}
710+
}
711+
}
712+
}
713+
}
714+
604715
typeSE []interface{}// slice of empty; notational compactness.
605716

606717
varreorderTests= []struct {

‎src/pkg/fmt/format.go‎

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -368,14 +368,25 @@ func (f *fmt) formatFloat(v float64, verb byte, prec, n int) {
368368
}else {
369369
num[0]='+'
370370
}
371+
// Special handling for infinity, which doesn't look like a number so shouldn't be padded with zeros.
372+
ifmath.IsInf(v,0) {
373+
iff.zero {
374+
deferfunc() {f.zero=true }()
375+
f.zero=false
376+
}
377+
}
371378
// num is now a signed version of the number.
372379
// If we're zero padding, want the sign before the leading zeros.
373380
// Achieve this by writing the sign out and then padding the unsigned number.
374381
iff.zero&&f.widPresent&&f.wid>len(num) {
375-
f.buf.WriteByte(num[0])
376-
f.wid--
382+
iff.space&&v>=0 {
383+
f.buf.WriteByte(' ')// This is what C does: even with zero, f.space means space.
384+
f.wid--
385+
}elseiff.plus||v<0 {
386+
f.buf.WriteByte(num[0])
387+
f.wid--
388+
}
377389
f.pad(num[1:])
378-
f.wid++// Restore width; complex numbers will reuse this value for imaginary part.
379390
return
380391
}
381392
// f.space says to replace a leading + with a space.
@@ -436,60 +447,46 @@ func (f *fmt) fmt_fb32(v float32) { f.formatFloat(float64(v), 'b', 0, 32) }
436447

437448
// fmt_c64 formats a complex64 according to the verb.
438449
func (f*fmt)fmt_c64(vcomplex64,verbrune) {
439-
f.buf.WriteByte('(')
440-
r:=real(v)
441-
oldPlus:=f.plus
442-
fori:=0; ;i++ {
443-
switchverb {
444-
case'b':
445-
f.fmt_fb32(r)
446-
case'e':
447-
f.fmt_e32(r)
448-
case'E':
449-
f.fmt_E32(r)
450-
case'f','F':
451-
f.fmt_f32(r)
452-
case'g':
453-
f.fmt_g32(r)
454-
case'G':
455-
f.fmt_G32(r)
456-
}
457-
ifi!=0 {
458-
break
459-
}
460-
f.plus=true
461-
r=imag(v)
462-
}
463-
f.plus=oldPlus
464-
f.buf.Write(irparenBytes)
450+
f.fmt_complex(float64(real(v)),float64(imag(v)),32,verb)
465451
}
466452

467453
// fmt_c128 formats a complex128 according to the verb.
468454
func (f*fmt)fmt_c128(vcomplex128,verbrune) {
455+
f.fmt_complex(real(v),imag(v),64,verb)
456+
}
457+
458+
// fmt_complex formats a complex number as (r+ji).
459+
func (f*fmt)fmt_complex(r,jfloat64,sizeint,verbrune) {
469460
f.buf.WriteByte('(')
470-
r:=real(v)
471461
oldPlus:=f.plus
462+
oldSpace:=f.space
463+
oldWid:=f.wid
472464
fori:=0; ;i++ {
473465
switchverb {
474466
case'b':
475-
f.fmt_fb64(r)
467+
f.formatFloat(r,'b',0,size)
476468
case'e':
477-
f.fmt_e64(r)
469+
f.formatFloat(r,'e',doPrec(f,6),size)
478470
case'E':
479-
f.fmt_E64(r)
471+
f.formatFloat(r,'E',doPrec(f,6),size)
480472
case'f','F':
481-
f.fmt_f64(r)
473+
f.formatFloat(r,'f',doPrec(f,6),size)
482474
case'g':
483-
f.fmt_g64(r)
475+
f.formatFloat(r,'g',doPrec(f,-1),size)
484476
case'G':
485-
f.fmt_G64(r)
477+
f.formatFloat(r,'G',doPrec(f,-1),size)
486478
}
487479
ifi!=0 {
488480
break
489481
}
482+
// Imaginary part always has a sign.
490483
f.plus=true
491-
r=imag(v)
484+
f.space=false
485+
f.wid=oldWid
486+
r=j
492487
}
488+
f.space=oldSpace
493489
f.plus=oldPlus
490+
f.wid=oldWid
494491
f.buf.Write(irparenBytes)
495492
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp